gpt4 book ai didi

c# - Ninject 的 Bind.ToMethod 使用 CQRS 的 Unity 等价物

转载 作者:太空宇宙 更新时间:2023-11-03 23:33:22 25 4
gpt4 key购买 nike

我正在关注这个 CQS 教程 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)));但这不起作用。

最佳答案

您会认为 InjectionFactory 是可行的方法。这编译:

container.RegisterType<IQueryFactory>(new ContainerControlledLifetimeManager(),
new InjectionFactory((c, x, o) => new QueryFactory(t => c.Resolve(x))));

问题是类型 x 始终是 IQueryFactory,因此无法获得您想要的返回 IQuery 的结果。

不幸的是,我认为当前的设计不太适合 Unity。

但是,通过一些细微的修改,您可以使工厂正常工作。有几种不同的方法可以做到这一点(例如,您可以在工厂中注入(inject)容器并从那里解析)但是在这个例子中我将使用字典。

首先我们修改工厂定义:

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;
}
}

但是,有些人反对让工厂依赖于容器实现。

另一种方法是摆脱工厂方法并直接注入(inject)查询;这将使依赖关系变得明显,但我可以看到您希望根据命令类型动态获取查询的场景。此外,我还看到了命令和查询之间的关系,这些关系可以用组合根中解析的开放泛型来处理。

关于c# - Ninject 的 Bind.ToMethod 使用 CQRS 的 Unity 等价物,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31383790/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com