我有一些工厂接口。
有些工厂不需要任何实现者,所以我可以按如下方式绑定它们。
IKernel kernel = new StandardKernel();
kernel.Bind(services => services
.From(AppDomain.CurrentDomain
.GetAssemblies()
.Where(a => a.FullName.Contains("MyProject")
&& !a.FullName.Contains("Tests")))
.SelectAllInterfaces()
.EndwingWith("Factory")
.BindToFactory());
只要我不需要为构造函数提供参数,哪个应该通过Method Injection提供,哪个工作完美无瑕。
此外,使用此代码,我也绑定了ICustomerManagementPresenterFactory
,并且它不受其实现者的约束。
ICustomerManagementPresenterFactory
public interface ICustomerManagementPresenterFactory {
CustomerManagementPresenter Create();
}
CustomerManagementPresenterFactory
public class CustomerManagementPresenterFactory : ICustomerManagementPresenterFactory {
public CustomerManagementPresenterFactory(ICustomerManagementView view
, ICustomerDetailPresenterFactory factory) {
this.factory = factory;
this.view = view;
}
public CustomerManagementPresenter Create() {
return new CustomerManagementPresenter(view, factory);
}
private readonly ICustomerDetailPresenterfactory factory;
private readonly ICustomerManagementView view;
}
所以,因为 CustomerManagementPresenter 的构造函数有两个参数,我希望实现一个工厂,它不需要为它创建的类的依赖项注入方法,并且我继续使用{{ 3}}
所以,我想从Constructor Injection中受益,并且仍然以不同的方式绑定两者。
我怎么能这样做?
答案 0 :(得分:1)
可悲的是,您无法检索类型列表"已选择"按惯例。 这意味着你必须在某种程度上解决它。
语法提供Where(Func<Type, bool> selector)
和Excluding(IEnumerable<Type> types)
方法。因此,在将接口工厂与.ToFactory()
绑定之前,您需要获取所有已实现工厂的接口。例如:
IKernel kernel = new StandardKernel();
IList<Type> implementedFactoryInterfaces = new List<Type>();
kernel.Bind(services => services
.From(AppDomain.CurrentDomain
.GetAssemblies()
.Where(a => a.FullName.Contains("MyProject")
&& !a.FullName.Contains("Tests")))
.SelectAllClasses()
.EndingWith("Factory")
.Where(classFactoryType =>
{
implementedFactoryInterfaces.Add(classFactoryType.GetInterfaces().Single());
return true;
})
.BindDefaultInterface());
kernel.Bind(services => services
.From(AppDomain.CurrentDomain
.GetAssemblies()
.Where(a => a.FullName.Contains("MyProject")
&& !a.FullName.Contains("Tests")))
.SelectAllInterfaces()
.EndingWith("Factory")
.Excluding(implementedFactoryInterfaces)
.BindToFactory());
另一种方法是实现一个绑定生成器,检查是否有传递接口的实现 - Type
并相应地创建绑定:
public class InterfaceAndClassFactoryBindingGenerator : IBindingGenerator
{
public IEnumerable<IBindingWhenInNamedWithOrOnSyntax<object>> CreateBindings(Type type, IBindingRoot bindingRoot)
{
if (!type.IsInterface)
{
throw new ArgumentOutOfRangeException("type", type, "is not an interface, but only interfaces are supported");
}
Type classImplementingTheFactoryInterface = type.Assembly.GetTypes()
.Where(t => t.IsClass)
.SingleOrDefault(type.IsAssignableFrom);
if (classImplementingTheFactoryInterface == null)
{
bindingRoot.Bind(type).ToFactory();
}
else
{
bindingRoot.Bind(type).To(classImplementingTheFactoryInterface);
}
}
}
IKernel kernel = new StandardKernel();
kernel.Bind(services => services
.From(AppDomain.CurrentDomain
.GetAssemblies()
.Where(a => a.FullName.Contains("MyProject")
&& !a.FullName.Contains("Tests")))
.SelectAllInterfaces()
.EndingWith("Factory")
.BindWith<InterfaceAndClassFactoryBindingGenerator>());