【问题标题】:Unity container resolve based on attributeUnity容器基于属性解析
【发布时间】:2017-05-18 12:27:16
【问题描述】:

我正在编写一个针对不同客户端具有不同类实现的应用程序。我们正在使用 CQRS,我想为每个客户端添加不同的命令和查询实现(如果不存在特定于客户端的客户端,则默认为默认)。

之前编写的应用程序只有一个客户端,这工作正常,但现在我们需要为每个客户端覆盖命令和客户端。关于如何做到这一点,我有很多想法,但感觉最干净,因为只需添加一组查询/命令即可轻松添加新客户端。

调度查询的代码如下:

 public InProcQueryDispatcher(
        IQueryHandlerFactory queryHandlerFactory,
        Action<Exception, IQuery> onHandlerFailed)
    {
        this.queryHandlerFactory = queryHandlerFactory;
        this.onHandlerFailed = onHandlerFailed;
        this.getHandlerMethod = typeof(IQueryHandlerFactory).GetMethod("GetHandler");
    }

    public async Task<TResult> Execute<TResult>(IQuery<TResult> query)
    {
        if (query == null)
        {
            throw new ArgumentNullException();
        }

        try
        {
            var queryHandler = this.ResolveHandler<TResult>(query.GetType());

            var task = (Task<TResult>) queryHandler.Handle((dynamic) query);

            return await task;
        }
        catch (Exception ex)
        {
            this.onHandlerFailed(ex, query);
            throw;
        }
    }

    private dynamic ResolveHandler<TResult>(Type queryType)
    {
        var getHandler = this.getHandlerMethod.MakeGenericMethod(queryType, typeof (TResult));
        return getHandler.Invoke(this.queryHandlerFactory, null);
    }
}

我现在希望能够将其更改如下:

`public async Task<TResult> Execute<TResult>(IQuery<TResult> query)
        {
            if (query == null)
            {
                throw new ArgumentNullException();
            }

            try
            {
                var queryHandler = this.ResolveHandler<TResult>(query.GetType(), query.ClientId);

                var task = (Task<TResult>) queryHandler.Handle((dynamic) query);

                return await task;
            }
            catch (Exception ex)
            {
                this.onHandlerFailed(ex, query);
                throw;
            }
        }

        private dynamic ResolveHandler<TResult>(Type queryType, Guid clientId)
        {
            var getHandler = this.getHandlerMethod.MakeGenericMethod(queryType, clientId, typeof (TResult));
            return getHandler.Invoke(this.queryHandlerFactory, null);
        }

谁能推荐我如何更新我的 getHandleMethod 以根据 clientID 解析正确的查询?

GetHandleMethod:

 public IQueryHandler<TQuery, TResult> GetHandler<TQuery, TResult>() where TQuery : class, IQuery<TResult>
    {
        return container.Resolve<IQueryHandler<TQuery, TResult>>();
    }

【问题讨论】:

    标签: c# asp.net dependency-injection unity-container cqrs


    【解决方案1】:

    使用 IoC,您的对象不应了解容器本身,因为您不将容器直接传递给构造函数是正确的。但是,您可以将工厂传递给您的类,然后它将用于解析。我发现将其与命名注册结合起来效果很好。您可以如何做到这一点的摘要将类似于以下内容:

    container.RegisterType<IQueryHandler<TQuery, TResult>, QueryHandlerVersionOne<TQuery, TResult>>("1");
    container.RegisterType<IQueryHandler<TQuery, TResult>, QueryHandlerVersionTwo<TQuery, TResult>>("2");
    
    container.RegisterType<Func<int, IQueryHandler<TQuery, TResult>>>(
        new InjectionFactory(c =>
            new Func<int, IQueryHandler<TQuery, TResult>>((clientID) =>
            {
                var handler = c.Resolve<IQueryHandler<TQuery, TResult>>(clientID.ToString());
    
                return handler;
            })));
    

    然后,在您的构造函数中,为工厂注入类型为Func&lt;int, IQueryHandler&lt;TQuery, TResult&gt;&gt; 添加一个参数。

    我回答了一个更长的例子in this post

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-04-03
      • 2019-04-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-24
      • 2016-11-04
      • 2012-09-27
      相关资源
      最近更新 更多