[英]Registering generic type with multiple constructors
I am trying to move from Unity to Simple Injector and having trouble getting the Injection to work with Simple Injector. 我正在尝试从Unity转移到Simple Injector,并且无法使Injection与Simple Injector一起使用。
Working Unity code is below 工作Unity代码如下
var container = new UnityContainer();
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
container.RegisterType(
typeof(ICacheManager<>),
new ContainerControlledLifetimeManager(),
new InjectionFactory((c, targetType, name) =>
CacheFactory.FromConfiguration(targetType.GenericTypeArguments[0], "myCache")));
My Attempts: 我的尝试:
var registration = Lifestyle.Singleton.CreateRegistration(
typeof(ICacheManager<>),
typeof(BaseCacheManager<>),
container);
container.AddRegistration(
serviceType: typeof(BaseCacheManager<>),
registration: registration);
I am getting the following error 我收到以下错误
For the container to be able to create
BaseCacheManager<Object>
it should have only one public constructor为了使容器能够创建
BaseCacheManager<Object>
它应该只有一个公共构造函数
There are several ways you can solve this in Simple Injector. 您可以通过多种方法在Simple Injector中解决此问题。
First of all, always let your components have a single constructor, since having multiple constructors is an anti-pattern . 首先,始终让您的组件具有单个构造函数,因为具有多个构造函数是一种反模式 。
Since however the supplied type is from an external library, it is impossible for you to change it. 但是,由于提供的类型来自外部库,因此您无法更改它。
What you can do instead is derive from this particular type and create a sub class that only has one constructor. 相反,您可以做的是从此特定类型派生并创建一个只有一个构造函数的子类。 This type can call into the specific constructor of the base class you are interested in:
这种类型可以调用您感兴趣的基类的特定构造函数:
class MyBaseClassManager<T> : BaseCacheManager<T>
{
public MyBaseClassManager([args]) : base([args]) { }
}
container.RegisterSingleton(typeof(ICacheManager<>), typeof(MyBaseCacheManager<>)):
In general however, you should prevent having your application code depend on abstractions that are not defined by the application, since this is a Dependency Inversion Principle (DIP) violation. 但是,通常,应避免让应用程序代码依赖于应用程序未定义的抽象,因为这是对依赖关系倒置原则 (DIP)的违反。 The DIP guides us into defining application-tailored abstractions.
DIP指导我们定义应用程序定制的抽象。 Based on such abstraction you can define an adapter that forwards the call to the external component.
基于这种抽象,您可以定义一个适配器,将调用转发到外部组件。 Example:
例:
// 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<>)):
If the number of closed types you need is limited, you can also register every closed version explicitly: 如果需要的封闭类型数量有限,则还可以显式注册每个封闭版本:
container.RegisterSingleton<ICacheManager<Foo>>(new BaseCacheManager<Foo>());
container.RegisterSingleton<ICacheManager<Bar>>(new BaseCacheManager<Bar>());
container.RegisterSingleton<ICacheManager<FooBar>>(new BaseCacheManager<FooBar>());
Yet another option is to override Constructor Resolution Behavior, as explained here . 另一个选择是重写构造函数解析行为,如解释在这里 。 You can do this
你可以这样做
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);
Yet another option is to hook onto the ResolveUnregisteredType` event although I would only advise this as last resort. 另一个选择是挂钩到ResolveUnregisteredType`事件,尽管我只建议这样做。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.