简体   繁体   English

向多个构造函数注册通用类型

[英]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.

相关问题 在 Simple Injector 中注册具有多个构造函数和字符串依赖项的类型 - Registering a type with multiple constructors and string dependency in Simple Injector 在类型“System.Collections.Generic.List”中发现多个构造函数错误 - Multiple Constructors Error found in type 'System.Collections.Generic.List' 将其他通用类型注册为已扫描 - Registering a different generic type as scanned 在Castle Windsor注册通用类型 - Registering generic type in Castle Windsor 具有多个构造函数的记录类型 - Record type with multiple constructors Autofac:如何使用多个类型参数注册泛型?使用EFGenRepo <T,TKey>注册IGenRepo <T,TKey> - Autofac: How do you register a generic with multiple type arguments? Registering IGenRepo<T, TKey> with EFGenRepo<T, TKey> 在 Autofac 中注册一个开放泛型类型 - Registering an open-generic type in Autofac 使用Generic复杂类型和AutoFac注册通用类型 - Registering Generic Types using Generic complex type with AutoFac 在 .NET Core (MS.DI) 中注册具有类型约束的泛型 - Registering generic type with type constraint in .NET Core (MS.DI) 注册一个开放的通用服务错误地要求我提供类型参数 - Registering an open Generic Service erroneously asks me for type arguments
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM