[英]Create a simple Query object
我创建了一个查询,如下所示:
public class FindPostEditModelByIdQuery : IQuery<PostEditModel> {
private readonly ILogger _logger;
private readonly ISession _session;
public FindPostEditModelByIdQuery(ISession session, ILogger logger) {
_logger = logger;
_session = session;
}
public async Task<PostEditModel> Run(int postId, out exception) {
// Code here
}
}
因此,基本上,在构造函数中,我通过IOC要求使用什么...
我希望这种方法允许以简单的方式使用异步,从而使事情保持简单。
几个问题:
在我的控制器中,我将使用许多命令...我想避免在构造函数中使用很多命令。 您认为注入请求命令的工厂是否可以? 我应该怎么做?
我是否正确使用异步?
您如何看待将异常作为参数传递? 将有可能创建一些东西来记录异常,而该异常会在Run方法上发生。 这有道理吗?
UPDATE
我发布的内容是尝试使与我正在使用的内容相比更易于使用异步。
我正在使用查询/答复和命令(当时我称它们为订单),并且有:
public interface IOrderHandler {
void Handle(Order order);
}
public interface IOrderHandler<TOrder> : IOrderHandler where TOrder : Order {
void Handle(TOrder order);
}
public interface IQueryHandler {
Reply Handle(Query query);
}
public interface IQueryHandler<TQuery, TReply> : IQueryHandler
where TQuery : Query
where TReply : Reply {
Reply Handle(TQuery query);
}
public abstract class OrderHandler : IOrderHandler {
public abstract void Handle(Order order); // Handle
}
public abstract class OrderHandler<TOrder> : OrderHandler, IOrderHandler<TOrder> where TOrder : Order {
public override void Handle(Order order) {
TOrder torder = (TOrder)order;
Handle(torder);
}
public abstract void Handle(TOrder order); // Handle
}
public abstract class QueryHandler<TQuery, TReply> : QueryHandler, IQueryHandler<TQuery, TReply>
where TQuery : Query
where TReply : Reply {
public override Reply Handle(Query query) {
TQuery tquery = (TQuery)query;
Reply treply = Handle(tquery);
return treply;
}
public abstract Reply Handle(TQuery query);
}
public abstract class QueryHandler : IQueryHandler {
public abstract Reply Handle(Query query);
}
public abstract class QueryHandler<TQuery, TReply> : QueryHandler, IQueryHandler<TQuery, TReply>
where TQuery : Query
where TReply : Reply {
public override Reply Handle(Query query) {
TQuery tquery = (TQuery)query;
Reply treply = Handle(tquery);
return treply;
}
public abstract Reply Handle(TQuery query);
}
public abstract class Order { } // Order
public abstract class Query { }
public abstract class Reply {
public Exception Exception { get; set; }
}
public interface IDispatcher {
void Send(Order order);
void Send(Order order, out Exception exception);
TReply Send<TReply>(Query query) where TReply : Reply, new();
}
public class Dispatcher : IDispatcher {
public void Send(Order order) {
Type type = typeof(IOrderHandler<>).MakeGenericType(order.GetType());
IOrderHandler handler = (IOrderHandler)ObjectFactory.GetInstance(type);
try {
handler.Handle(order);
} catch (Exception exception) {
ILogger logger = ObjectFactory.GetInstance<ILogger>();
logger.Send(exception);
if (Debugger.IsAttached) throw;
}
}
public void Send(Order order, out Exception exception) {
Type type = typeof(IOrderHandler<>).MakeGenericType(order.GetType());
IOrderHandler handler = (IOrderHandler)ObjectFactory.GetInstance(type);
exception = null;
try {
handler.Handle(order);
} catch (Exception ex) {
ILogger logger = ObjectFactory.GetInstance<ILogger>();
logger.Send(ex);
exception = ex;
if (Debugger.IsAttached) throw;
}
}
public TReply Send<TReply>(Query query) where TReply : Reply, new() {
Type type = typeof(IQueryHandler<,>).MakeGenericType(query.GetType(), typeof(TReply));
IQueryHandler handler = (IQueryHandler)ObjectFactory.GetInstance(type);
try {
return (TReply)handler.Handle(query);
} catch (Exception exception) {
ILogger logger = ObjectFactory.GetInstance<ILogger>();
logger.Send(exception);
if (Debugger.IsAttached) throw;
return new TReply { Exception = exception };
}
}
} // Dispatcher
一些注意事项和问题
它是我在控制器上注入的调度程序。 然后我用它:
_dispacther.Send(new FindPostByIdQuery(22));
我不确定在调度程序中记录异常是否是一个好方法。 基本上,我记录了服务层上发生的所有异常。
我正在考虑的一件事是拥有一个可以附加的ExceptionHandler。
但是我不确定这是否可能。 你怎么看?
我不确定如果需要,如何使我的代码与异步一起使用。
有谁知道如何测试这种模式? 对我来说,这并不容易。
#1:您的控制器不应使用那么多注入的命令。 构造函数过度注入通常是需要进一步分解对象的气味。 诸如日志记录,异常处理之类的问题通常是交叉的,最好在外层进行处理。
#2:几乎没有任何代码可以得出结论。 从签名的角度来看,这是可以的,尽管就像我在上面说的那样,您可以无out exception
消除它。 调用方需要使用ContinueWith
或类似方法处理异步链中的错误。
task.ContinueWith(x => x.Exception.Handle(ex =>
{
logger.Error(ex.Message, ex);
return false;
}), TaskContinuationOptions.OnlyOnFaulted);
#3:异常记录不应由查询对象负责,而应由位于其上方的对象-使用动作过滤器,或在调用者级别或服务或更高级别-使用面向方面的编程。
更新:
看一下ShortBus 。 除非您想自己动手做,否则它就拥有您正在寻找的所有东西,包括异步处理程序 , 冒泡异常和单元测试的功能。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.