在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>();
答案 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>
抽象,而是指定特定的工厂。这使得事情变得更加明显,因为你应该有一些工厂,这不会导致大量的样板代码。