2013-02-27 138 views
4

的注入變化實現服務定位器我有以下幾點:與泛型類型

public interface IConverter<TValue, TConverted> 
{  
} 

public interface IConverterProvider 
{ 
    IConverter<TValue, TConverted> GetConverter<TValue, TConverted>(); 
} 

用一個例子,在設置綁定:

Bind<IConverter<System.Int32, System.String>>().To<Int32ToStringConverter>(); 
Bind<IConverter<System.Guid, System.String>>().To<GuidToStringConverter>(); 

所以,我有固定的轉換器和無重複的集合綁定。

[問題] 我的問題是我該如何去實現IConverterProvider並注入可用綁定映射到單例的字典?換句話說,如何避免運行時服務定位器模式。

目前我只是使用NInject內核來解決每一次,但我相信這是一種反模式。我想是這樣的:

public class ConverterProvider : IConverterProvider 
{ 
    private Dictionary<Type, object> _converters; 

    public ConverterProvider(Dictionary<Type, object> converters) 
    { 
     _converters = converters; 
    } 

    public IConverter<TValue, TConverted> GetConverter<TValue, TConverted>() 
    { 
     var fullTypeResolve = typeof (IConverter<,>).MakeGenericType(typeof (TValue), typeof (TConverted)); 

     return _converters.Where(x => x.Key == fullTypeResolve).Select(x=>x.Value).Cast<IConverter<TValue, TConverted>>().Single(); 
    } 
} 

但是,這有效地要求我能夠從依賴注入內核解決,並得到所有的列表IConverter <,>,和我以前這樣做的嘗試來自NInject尚未成功。

回答

1

這是由Ninject.Extensions.Factory

Bind<IConverter<System.Int32, System.String>>().To<Int32ToStringConverter>(); 
Bind<IConverter<System.Guid, System.String>>().To<GuidToStringConverter>(); 
Bind<IConverterProvider>().ToFactory(); 

支持沒有實施所需

重命名GetConverterCreateConverter或其他名稱不獲取

開始
0

我通常是這樣做的工廠(或供應商,你在這裏):

public class ConverterFactory : IConverterFactory 
{ 
    private readonly IResolutionRoot resolutionRoot; 

    public ConverterFactory(IResolutionRoot resolutionRoot) 
    { 
     this.resolutionRoot = resolutionRoot; 
    } 

    public IConverter<TValue, TConverted> CreateConverter() 
    { 
     Type converterType = typeof(IConverter<,>).MakeGenericType(typeof(TValue), typeof(TConverted)); 
     return this.resolutionRoot.Get(converterType); 
    } 
} 

我知道我們不是真的要使用Ninject在運行時創建的東西,但確實有時它的不可避免的。爲了得到單身人士的行爲,只需定義InSingletonScope()即可。

如果類型不是通用的,那麼你可以注入接口的所有實現,而不是IResolutionRoot,然後在運行時選擇一個。我有一個解析器工廠有點像這樣:

public class ParserFactory : IParserFactory 
{ 
    private readonly IEnumerable<IParser> parsers; 

    public ParserFactory(IEnumerable<IParser> parsers) 
    { 
     this.parsers = parsers; 
    } 

    public IParser CreateParser(string someInput) 
    { 
     foreach (var parser in this.parsers) 
     { 
      if (parser.CanParse(someInput)) 
      { 
       return parser; 
      } 
     } 
    } 
} 

Ninject將自動注入一個IEnumerable含有該接口的所有具體實施方式中,所以增加新的實現方式是作爲添加映射一樣簡單。我不知道如何用泛型類型來做到這一點,雖然你不能說IEnumerable<IConverter<,>>