我正在关注此CQS tuturiol https://github.com/Code-First/CQS-Sample并使用Ninject。
我目前正在使用Unity并试图将其转换为:
Bind<IQueryFactory>().ToMethod(t => new QueryFactory(x => Container.Current.Resolve(x))).InTransientScope();
我的查询工厂如下所示:
public class QueryFactory : IQueryFactory
{
private readonly Func<Type, object> _resolveCallback;
public QueryFactory(Func<Type, object> resolveCallback)
{
_resolveCallback = resolveCallback;
}
public T ResolveQuery<T>()
where T : class, IQuery
{
return _resolveCallback(typeof (T)) as T;
}
}
我尝试了container.RegisterType<IQueryFactory>(t => new InjectionFactory(u => u.Resolve(u)));
,但这不起作用。
答案 0 :(得分:3)
你认为注射工厂将是最佳选择。这编译:
container.RegisterType<IQueryFactory>(new ContainerControlledLifetimeManager(),
new InjectionFactory((c, x, o) => new QueryFactory(t => c.Resolve(x))));
问题是x类型总是IQueryFactory,因此不能获得你想要的返回IQuery的结果。
不幸的是,我不认为当前的设计非常适合Unity。
然而,通过一些细微的修改,您可以让工厂工作。有几种不同的方法可以做到这一点(例如,你可以在工厂注入容器并从那里解决)但是在这个例子中我会使用字典。
首先我们改变工厂定义:
public class QueryFactory : IQueryFactory
{
private readonly IDictionary<Type, Func<IQuery>> _factoryQueries;
public QueryFactory(IDictionary<Type, Func<IQuery>> factoryQueries)
{
this._factoryQueries = factoryQueries;
}
public T ResolveQuery<T>() where T : class, IQuery
{
return this._factoryQueries[typeof(T)]() as T;
}
基本上,Func<Type, object> resolveCallback
被交换为包含Funcs的IDictionary,用于创建所有支持的IQuery类型。
接下来注册IDictionary和IQueryFactory:
IUnityContainer container = new UnityContainer();
// Register all IQuery's
container.RegisterType<IActiveUsersQuery, ActiveUsersQuery>();
container.RegisterType<IUserByEmailQuery, UserByEmailQuery>();
IDictionary<Type, Func<IQuery>> factoryQueries = new Dictionary<Type, Func<IQuery>>()
{
{ typeof(IActiveUsersQuery), () => container.Resolve<IActiveUsersQuery>() },
{ typeof(IUserByEmailQuery), () => container.Resolve<IUserByEmailQuery>() },
};
// Register mapping
container.RegisterInstance<IDictionary<Type, Func<IQuery>>>(factoryQueries);
container.RegisterType<IQueryFactory, QueryFactory>();
var factory = container.Resolve<IQueryFactory>();
factory.ResolveQuery<IActiveUsersQuery>().Execute();
factory.ResolveQuery<IActiveUsersQuery>().Execute();
如上所述,一个更简单的QueryFactory方法依赖于容器:
public class QueryFactory : IQueryFactory
{
private readonly IUnityContainer container;
public QueryFactory(IUnityContainer container)
{
this.container = container;
}
public T ResolveQuery<T>()
where T : class, IQuery
{
return this.container.Resolve(typeof(T)) as T;
}
}
但是,有些人会反对让工厂依赖于容器实现。
另一种方法是摆脱工厂方法并直接注入查询;这会使依赖关系明显,但我可以看到你想要根据命令类型动态获取查询的场景。此外,我已经看到了命令和查询之间的关系,这些关系可以使用在组合根中解析的开放式泛型来处理。