2013-02-27 133 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<,>>