使用Unity(容器抽象)定义自定义autofac?

时间:2014-08-18 13:20:55

标签: c# ninject unity-container

在Ninject中你可以做到

kernel.Bind(typeof(Func<,>)).ToMethod(CreateFunc).When(VerifyFactoryFunction);

这意味着你可以做一些魔术和反思

public MyConstructor(Func<Type, IResult> factory) {
   this.result = factory(typeof(SomeType));
}

而不是

public MyConstructor(IUnityContainer container) {
   this.result = container.Resolve(typeof(SomeType));
}

Unity可以实现吗?我做了这个扩展方法

public static void RegisterContainerAbstraction<TTo>(this IUnityContainer self)
{
    self.RegisterInstance<Func<Type, TTo>>(t => (TTo)self.Resolve(t));
}

您需要为要抽象容器的所有类型调用它,例如

container.RegisterContainerAbstraction<IResult>();

1 个答案:

答案 0 :(得分:1)

Ninject允许的是一个特殊功能,这更像是一种功能性方法。默认情况下,.NET中的DI库采用更加面向对象的方法,这意味着对创建和自动连接类的支持通常非常好,而函数的创建和计算支持很差。

因此,开箱即用,Unity中没有任何内容可以让您这样做,但这可以通过创建自定义界面和实现轻松解决:

// Abstraction: Part of your core library
public interface IFactory<TResult>
{
    TResult Create(Type type);
}

// Implementation: Part of your composition root
private sealed CreateFuncFactory<TResult> : IFactory<TResult>
{
    // Since we're in the Composition Root, its okay to depend
    // on the container here. See: https://bit.ly/1mdaLYG 
    private readonly IUnityContainer container;
    public CreateFuncFactory(IUnityContainer container) {
        this.container = container;
    }

    public TResult Create(Type type) {
        return (TResult)container.Resolve(type);
    }
}

您可以在Unity中注册,如下所示:

container.RegisterType(typeof(IFactory<>), typeof(CreateFuncFactory<>));

但是,如果正确应用依赖注入,则对工厂抽象的需求要少得多。它们仍然有用,但您可能只需要一个完整的应用程序。因此,在这方面,不要使用一个通用的Func<,>IFactory<T>抽象,而是指定特定的工厂。这使得事情变得更加明显,因为你应该有一些工厂,这不会导致大量的样板代码。