有几种方法可以在 Simple Injector 中解决这个问题。
首先,总是让你的组件有一个构造函数,因为有多个构造函数是一种反模式。
但是,由于提供的类型来自外部库,因此您无法更改它。
相反,您可以做的是从这个特定类型派生并创建一个只有一个构造函数的子类。此类型可以调用您感兴趣的基类的特定构造函数:
class MyBaseClassManager<T> : BaseCacheManager<T>
{
public MyBaseClassManager([args]) : base([args]) { }
}
container.RegisterSingleton(typeof(ICacheManager<>), typeof(MyBaseCacheManager<>)):
然而,一般来说,您应该防止您的应用程序代码依赖于应用程序未定义的抽象,因为这违反了依赖倒置原则(DIP)。DIP 指导我们定义应用程序定制的抽象。基于这样的抽象,您可以定义一个将调用转发到外部组件的适配器。例子:
// In the application's core layer
public interface ICache<T>
{
}
// Adapter in the Composition Root
public sealed class CacheManagerCacheAdapter<T> : ICache<T>
{
private static BaseCacheManager<T> manager = new BaseCacheManager<T>();
// Implement ICache<T> methods
public object GetByKey(object key)
{
// translate and forward to the external component
return this.manager[key];
}
}
// Registration
container.RegisterSingleton(typeof(ICache<>), typeof(CacheManagerCacheAdapter<>)):
如果您需要的封闭类型数量有限,您还可以显式注册每个封闭版本:
container.RegisterSingleton<ICacheManager<Foo>>(new BaseCacheManager<Foo>());
container.RegisterSingleton<ICacheManager<Bar>>(new BaseCacheManager<Bar>());
container.RegisterSingleton<ICacheManager<FooBar>>(new BaseCacheManager<FooBar>());
另一种选择是覆盖构造函数解析行为,如此处所述。你可以这样做
public class CacheManagerConstructorResolutionBehavior
: IConstructorResolutionBehavior {
private readonly IConstructorResolutionBehavior org;
public CacheManagerConstructorResolutionBehavior(IConstructorResolutionBehavior org) {
this.org = org;
}
public ConstructorInfo GetConstructor(Type serviceType, Type implementationType) {
if (implementationType.IsGenericType &&
implementationType.GetGenericTypeDefinition() == typeof(BaseCacheManager<>)) {
return implementationType.GetConstructors()
.OrderByDescending(c => c.GetParameters().Length)
.First();
}
return this.org.GetConstructor(serviceType, implementationType);
}
}
var container = new Container();
container.Options.ConstructorResolutionBehavior =
new CacheManagerConstructorResolutionBehavior(
container.Options.ConstructorResolutionBehavior);
另一种选择是挂钩ResolveUnregisteredType` 事件,尽管我只建议将此作为最后的手段。