簡體   English   中英

創建一個簡單的查詢對象

[英]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要求使用什么...

我希望這種方法允許以簡單的方式使用異步,從而使事情保持簡單。

幾個問題:

  1. 在我的控制器中,我將使用許多命令...我想避免在構造函數中使用很多命令。 您認為注入請求命令的工廠是否可以? 我應該怎么做?

  2. 我是否正確使用異步?

  3. 您如何看待將異常作為參數傳遞? 將有可能創建一些東西來記錄異常,而該異常會在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

一些注意事項和問題

  1. 它是我在控制器上注入的調度程序。 然后我用它:

    _dispacther.Send(new FindPostByIdQuery(22));

  2. 我不確定在調度程序中記錄異常是否是一個好方法。 基本上,我記錄了服務層上發生的所有異常。

    我正在考慮的一件事是擁有一個可以附加的ExceptionHandler。

    但是我不確定這是否可能。 你怎么看?

  3. 我不確定如果需要,如何使我的代碼與異步一起使用。

  4. 有誰知道如何測試這種模式? 對我來說,這並不容易。

#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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM