gpt4 book ai didi

c# - 没有服务定位器的 CQRS 调度程序

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

我正在基于现有的 Asp.Net 4.5 解决方案创建新的 Asp.Net Core 解决方案。

当前的解决方案使用 Microsoft Unity Container 并且基础设施引用了服务定位器。

我想摆脱服务定位器并避免在我的新基础架构中引用特定的 DI 容器。

我遇到了一个问题,想出一个很好的方法来替换当前的命令/查询/事件调度程序,而不需要任何 DI 容器依赖性。

这是我的 Dispatcher 类

public class Dispatcher : IDispatcher
{
private const string HandleMethodName = "Handle";

public TResponse Request<TResponse>(IQuery<TResponse> query)
{
Type queryType = query.GetType();

// used for when OperationResult<object> was used
Type operationResultTrueReturnType = typeof(TResponse);
if (operationResultTrueReturnType == typeof(object))
{
operationResultTrueReturnType = queryType.GetInterface(typeof(IQuery<>).Name).GenericTypeArguments[0];
}

Type handlerType = typeof(IQueryHandler<,>).MakeGenericType(query.GetType(), operationResultTrueReturnType);
return ExecuteHandler<TResponse>(handlerType, query, queryType);
}

public OperationResult Submit(ICommand command)
{
Type commandType = command.GetType();

var baseTypeAttribute = (CommandBaseTypeAttribute)commandType.GetCustomAttributes(typeof(CommandBaseTypeAttribute), false).FirstOrDefault();
if (baseTypeAttribute != null)
commandType = baseTypeAttribute.BaseType;

try
{
Type handlerType = typeof(ICommandHandler<>).MakeGenericType(commandType);
return ExecuteHandler<OperationResult>(handlerType, command, commandType);
}
catch (InvalidOperationException ex)
{
return new OperationResult(OperationResultStatus.Failure, ex.Message);
}
}

public OperationResult<TResult> Submit<TResult>(ICommand<TResult> command)
{
Type commandType = command.GetType();

var baseTypeAttribute = (CommandBaseTypeAttribute)commandType.GetCustomAttributes(typeof(CommandBaseTypeAttribute), false).FirstOrDefault();
if (baseTypeAttribute != null)
commandType = baseTypeAttribute.BaseType;

try
{
Type handlerType = typeof(ICommandHandler<,>).MakeGenericType(commandType, typeof(TResult));
return ExecuteHandler<OperationResult<TResult>>(handlerType, command, commandType);
}
catch (InvalidOperationException ex)
{
return new OperationResult<TResult>(OperationResultStatus.Failure, default(TResult), ex.Message);
}
}

public void Raise(IDomainEvent domainEvent)
{
Type domainEventType = domainEvent.GetType();

try
{
Type handlerType = typeof(ICommandHandler<>).MakeGenericType(domainEventType);
ExecuteHandler(handlerType, domainEvent, domainEventType);
}
catch (InvalidOperationException)
{

}
}

private static void ExecuteHandler(Type handlerType, object argument, Type argumentType)
{
object handler = ServiceLocator.Current.GetInstance(handlerType);

if (handler == null)
throw new ConfigurationErrorsException("Handler not registered for type " + argumentType.Name);

try
{
MethodInfo handleMethod = handlerType.GetMethod(HandleMethodName, new[] { argumentType });
handleMethod.Invoke(handler, new[] { argument });
}
catch (TargetInvocationException ex)
{
if (ex.InnerException != null)
throw ex.InnerException;
throw;
}
}

private static TReturnValue ExecuteHandler<TReturnValue>(Type handlerType, object argument, Type argumentType)
{
object handler = ServiceLocator.Current.GetInstance(handlerType);

if (handler == null)
throw new ConfigurationErrorsException("Handler not registered for type " + argumentType.Name);

try
{
MethodInfo handleMethod = handlerType.GetMethod(HandleMethodName, new[] { argumentType });
return (TReturnValue)handleMethod.Invoke(handler, new[] { argument });
}
catch (TargetInvocationException ex)
{
if (ex.InnerException != null)
throw ex.InnerException;
throw;
}
}
}

ExecuteHandler 有 ServiceLocator 调用。

如何在不使用它的情况下处理这个问题?

最佳答案

我喜欢评论中提供的建议。如果您想抽象出服务定位器,则让调度程序显式依赖于将用于执行解析的抽象服务提供者(如 IServiceProvider)。

public class Dispatcher : IDispatcher {
private readonly IServiceProvider serviceProvider;

public Dispatcher (IServiceProvider serviceProvider) {
this.serviceProvider = serviceProvider;
}

//...other code removed for brevity

private object GetService(Type serviceType) {
return serviceProvider.GetService(serviceType);
}

private void ExecuteHandler(Type handlerType, object argument, Type argumentType) {
object handler = GetService(handlerType);

if (handler == null)
throw new ConfigurationErrorsException("Handler not registered for type " + argumentType.Name);

try {
MethodInfo handleMethod = handlerType.GetMethod(HandleMethodName, new[] { argumentType });
handleMethod.Invoke(handler, new[] { argument });
} catch (TargetInvocationException ex) {
if (ex.InnerException != null)
throw ex.InnerException;
throw;
}
}

private TReturnValue ExecuteHandler<TReturnValue>(Type handlerType, object argument, Type argumentType) {
object handler = GetService(handlerType);

if (handler == null)
throw new ConfigurationErrorsException("Handler not registered for type " + argumentType.Name);

try {
MethodInfo handleMethod = handlerType.GetMethod(HandleMethodName, new[] { argumentType });
return (TReturnValue)handleMethod.Invoke(handler, new[] { argument });
} catch (TargetInvocationException ex) {
if (ex.InnerException != null)
throw ex.InnerException;
throw;
}
}
}

调度程序现在不再与服务定位器反模式紧密耦合,并允许使用任何派生的提供程序。这使您可以避免引用特定的 DI 容器。

关于c# - 没有服务定位器的 CQRS 调度程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45064268/

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