在依赖关系解析期间获取类类型

时间:2015-05-05 12:07:30

标签: c# dependency-injection unity-container constructor-injection

为我的Unity容器注册一个类型时,我需要将调用类的类型传入已解析对象的构造函数。

这是我将一些接口注入构造函数的类。

namespace MyNamespace
{
    internal class ProcessingService: IProcessingService
    {
        private readonly ISomeClass1 someClass1;
        private readonly ISomeClass2 someClass2;

        public ProcessingService(ISomeClass1 someClass1, ISomeClass2 someClass2)
        {
            this.someClass1 = someClass1;
            this.someClass2 = someClass2;
        }
    }
}

SomeClass2期望构造函数中的Type:

public class SomeClass2
{
    public SomeClass2(Type type)
    {
        //...
    }
}

这是我设置容器的Unity bootstrap类。现在,对于ISomeClass2,当它解析为SomeClass2时,它需要传入ProcessingService类型。

namespace MyNamespace
{
    public class UnityBootstrap : IUnityBootstrap
    {
        public IUnityContainer Configure(IUnityContainer container)
        {
            return container
                .RegisterType<ISomeClass1, SomeClass1>()
                .RegisterType<ISomeClass2>(new InjectionFactory(fac =>
                {
                    // IMethodBase.GetCurrentMethod().DeclaringType is returning MyNamespace.UnityBootstrap
                    // whereas I need to get MyNamespace.ProcessingService
                    return new SomeClass2(MethodBase.GetCurrentMethod().DeclaringType);
                }));
        }
    }
}

有没有办法使用InjectionFactory(或我的Configure方法中的其他方式)执行此操作?

3 个答案:

答案 0 :(得分:2)

如果您可以控制ProcessingService,则可以在SomeClass2周围创建一个通用包装,然后使用开放式泛型注册它。但这需要您修改ProcessingService的构造函数。

public interface IGenericSomeClass2<T>: ISomeClass2 {}

public class GenericSomeClass2<T>: IGenericSomeClass2<T>
{
    private readonly ISomeClass2 someClass2;
    public GenericSomeClass2()
    {
        this.someClass2 = new SomeClass2(typeof(T));
    }
    // Pass-through implementation
}

public IUnityContainer Configure(IUnityContainer container)
{
    return container
        .RegisterType<ISomeClass1, SomeClass1>()
        .RegisterType(typeof(IGenericSomeClass2<>), typeof(GenericSomeClass2<>));
}

internal class ProcessingService: IProcessingService
{
    private readonly ISomeClass1 someClass1;
    private readonly ISomeClass2 someClass2;

    public ProcessingService(ISomeClass1 someClass1, IGenericSomeClass2<ProcessingService> someClass2)
    {
        this.someClass1 = someClass1;
        this.someClass2 = someClass2;
    }
}

答案 1 :(得分:0)

恕我直言,这个问题有两个观点:

1)如果SomeClass2始终使用类型ProcessingService,那么您可以将类型参数直接传递到InjectionFactory

container.RegisterType<ISomeClass2>(new InjectionFactory(_ =>
{
    return new SomeClass2(typeof(ProcessingService));
}));

2)否则,如果类型参数在整个应用程序中不同,则应考虑向接口ISomeClass2添加注册方法,并在构造函数中注册类型以强调依赖性/变体。

public interface ISomeClass2
{
    void DoSomething();
    void RegisterProcessingServiceType(Type processingServiceType);
}

public class SomeClass2 : ISomeClass2
{
    private Type _type;

    public void DoSomething()
    {
        if(_type == null)
            throw InvalidOperationException("Register processing service type before doing stuff.");
        // actually do something
    }

    public void RegisterProcessingServiceType(Type serviceType)
    {
        _type = serviceType;
    }
}

internal class ProcessingService: IProcessingService
{
    private readonly ISomeClass1 someClass1;
    private readonly ISomeClass2 someClass2;

    public ProcessingService(ISomeClass1 someClass1, ISomeClass2 someClass2)
    {
        this.someClass1 = someClass1;
        this.someClass2 = someClass2;
        this.someClass2.RegisterProcessingServiceType(this.GetType());
    }
}

答案 2 :(得分:0)

如果您不控制ProcessingService(或SomeClass2的其他使用者),您可以自定义这些使用者的注册。这种方法更具侵入性,因为您必须为每个消费者创建一个注射工厂。

container
    .RegisterType<IProcessingService, ProcessingService>(new InjectionFactory((c, type, name) =>
    {
        return new ProcessingService(c.Resolve<ISomeClass1>(), new SomeClass2(type));
    }));