[英]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.