有没有办法让C#泛型处理这种情况

有没有办法让C#泛型处理这种情况,c#,generics,C#,Generics,当出现以下情况时,我对充斥着行的代码感到不满意 var queryResult = _queryDispatcher.Dispatch<CustomerByIdQuery, CustomerByIdQueryResult>(customerByIdQuery).Customer; 有没有办法用泛型来实现这一点 这是密码 interface IQuery{} interface IQueryResult{} interface IQueryHandler&l

当出现以下情况时,我对充斥着行的代码感到不满意

var queryResult = _queryDispatcher.Dispatch<CustomerByIdQuery, CustomerByIdQueryResult>(customerByIdQuery).Customer;
有没有办法用泛型来实现这一点

这是密码

    interface IQuery{}
    interface IQueryResult{}

    interface IQueryHandler<TQuery, TQueryResult> : where TQueryResult:IQueryResult  where TQuery:IQuery
    {
      TQueryResult Execute(TQuery query);
    }

    interface IQueryDispatcher
    {
      TQueryResult Dispatch<TQuery, TQueryResult>(TQuery query) where TQuery:IQuery where TQueryResult:IQueryResult
    }

    class GenericQueryDispatcher : IQueryDispatcher
    {
      public TQueryResult Dispatch<TQuery, TQueryResult>(TQuery parms)
      {
        var queryHandler = queryRegistry.FindQueryHandlerFor(TQuery);
        queryHandler.Execute
      }
    }

    class CustomerByIdQuery : IQuery
    {
      public int Id { get; set; }
    }

    class CustomerByIdQueryResult : IQueryResult
    {
      public Customer {get; set;}
    }

    class CustomerByIdQueryHandler : IQueryHandler
    {
      public CustomerByIdQueryResult  Execute(TQuery query)
      {
        var customer = _customerRepo.GetById(query.Id);
        return new CustomerByIdQueryResult(){Customer = customer};
      }
    }


  public class SomeClassThatControlsWorkFlow
  {
    IQueryDispatcher _queryDispatcher;

    public SomeClassThatControlsWorkFlow(IQueryDispatcher queryDispatcher)
    {
      _queryDispatcher = queryDispatcher;
    }

    public void Run()
    {
      var customerByIdQuery = new CustomerByIdQuery(){Id=1};
      //want to change this line
      var customer = _queryDispatcher.Dispatch<CustomerByIdQuery, CustomerByIdQueryResult>(customerByIdQuery).Customer;     

    }
  }

是的,这是可能的,但是您必须使
Dispatch
方法的参数通用(这样,编译器可以从方法参数推断类型参数)。为此,您首先需要一个通用版本的
IQuery
IQueryResult
接口:

interface IQuery<TQuery, TQueryResult> : IQuery {}
interface IQueryResult<T> : IQueryResult 
{ 
    T Result { get; }
}
class CustomerByIdQuery : IQuery, IQuery<int, Customer>
{
  public int Id { get; set; }
}
class CustomerByIdQueryResult : IQueryResult, IQueryResult<Customer>
{
  public Customer Result {get; set;}
}
现在,您可以为接受通用参数的
Dispatch
添加重载:

interface IQueryDispatcher
{
    IQueryResult<TQueryResult> Dispatch<TQuery, TQueryResult>(IQuery<TQuery, TQueryResult> parms);
}

class GenericQueryDispatcher : IQueryDispatcher
{
  public TQueryResult Dispatch<TQuery, TQueryResult>(IQuery<TQuery, TQueryResult> parms)
  {
    // TODO implement
  }
}

我无法摆脱演员阵容,但这正是我想要的

    public interface IQueryDispatcher
  {
    TQueryResult Dispatch<TParameter, TQueryResult>(IQuery<TQueryResult> query)
      where TParameter : IQuery<TQueryResult>
      where TQueryResult : IQueryResult;
  }
  public interface IQueryHandler<in TQuery, out TQueryResult>
    where TQuery : IQuery<TQueryResult>
    where TQueryResult : IQueryResult
  {
    TQueryResult Retrieve(TQuery query);
  }


  public interface IQueryResult { }



  public interface IQuery { }
  public interface IQuery<TQueryResult> : IQuery { }


  public class QueryDispatcher : IQueryDispatcher
  {
    readonly IQueryHandlerRegistry _queryRegistry;

    public QueryDispatcher(IQueryHandlerRegistry queryRegistry)
    {
      _queryRegistry = queryRegistry;
    }

    public TQueryResult Dispatch<TQuery, TQueryResult>(IQuery<TQueryResult> query)
      where TQuery : IQuery<TQueryResult>
      where TQueryResult : IQueryResult
    {
      var handler = _queryRegistry.FindQueryHandlerFor<TQuery, TQueryResult>(query);

       //CANT GET RID OF CAST
      return handler.Retrieve((TQuery)query);
    }
  }

  public interface IQueryHandlerRegistry
  {
    IQueryHandler<TQuery, TQueryResult> FindQueryHandlerFor<TQuery, TQueryResult>(IQuery<TQueryResult> query) 
      where TQuery : IQuery<TQueryResult> 
      where TQueryResult : IQueryResult;
  }

  public class GetCustByIdAndLocQuery : IQuery<CustByIdAndLocQueryResult>
  {
    public string CustName { get; set; }
    public int LocationId { get; set; }

    public GetCustByIdAndLocQuery(string name, int locationId)
    {
      CustName = name;
      LocationId = locationId;
    }
  }

  public class CustByIdAndLocQueryResult : IQueryResult
  {
    public Customer Customer { get; set; }
  }

  public class GetCustByIdAndLocQueryHandler : IQueryHandler<GetCustByIdAndLocQuery, CustByIdAndLocQueryResult>
  {
    readonly ICustomerGateway _customerGateway;

    public GetCustByIdAndLocQueryHandler(ICustomerGateway customerGateway)
    {
      _customerGateway = customerGateway;
    }

    public CustByIdAndLocQueryResult Retrieve(GetCustByIdAndLocQuery query)
    {
      var customer = _customerGateway.GetAll()
                        .SingleOrDefault(x => x.LocationId == query.LocationId && x.CustomerName == query.CustName);

      return new CustByIdAndLocQueryResult() { Customer = customer };
    }
  }

  public interface ICustomerGateway
  {
    IEnumerable<Customer> GetAll();
  }

  public class Customer
  {
    public string CustomerName { get; set; }
    public int LocationId { get; set; }

    public bool HasInsurance { get; set; }
  }
公共接口调度程序
{
TQueryResult调度(IQuery查询)
其中t参数:iquiry
其中TQueryResult:IQueryResult;
}
公共接口IQueryHandler
问:伊奎里在哪里
其中TQueryResult:IQueryResult
{
TQueryResult检索(TQuery查询);
}
公共接口IQueryResult{}
公共接口IQuery{}
公共接口IQuery:IQuery{}
公共类QueryDispatcher:IQueryDispatcher
{
只读IQueryHandlerRegistry\u queryRegistry;
公共查询Dispatcher(IQueryHandlerRegistry查询注册表)
{
_queryRegistry=queryRegistry;
}
公共TQueryResult调度(IQuery查询)
问:伊奎里在哪里
其中TQueryResult:IQueryResult
{
var handler=\u queryRegistry.FindQueryHandlerFor(查询);
//摆脱不了石膏
return handler.Retrieve((TQuery)查询);
}
}
公共接口IQueryHandlerRegistry
{
IQueryHandler FindQueryHandlerFor(iQueryQuery)
问:伊奎里在哪里
其中TQueryResult:IQueryResult;
}
公共类GetCustByIdAndLocQuery:IQuery
{
公共字符串CustName{get;set;}
public int LocationId{get;set;}
公共GetCustByIdAndLocQuery(字符串名称,int locationId)
{
CustName=名称;
LocationId=LocationId;
}
}
公共类CustByIdAndLocQueryResult:IQueryResult
{
公共客户客户{get;set;}
}
公共类GetCustByIdAndLocQueryHandler:IQueryHandler
{
只读ICCustomerGateway\u customerGateway;
公共GetCustByIdAndLocQueryHandler(ICCustomerGateway customerGateway)
{
_customerGateway=customerGateway;
}
公共CustByIdAndLocQueryResult检索(GetCustByIdAndLocQuery查询)
{
var customer=\u customerGateway.GetAll()
.SingleOrDefault(x=>x.LocationId==query.LocationId&&x.CustomerName==query.CustName);
返回新的CustByIdAndLocQueryResult(){Customer=Customer};
}
}
公共接口ICustomerGateway
{
IEnumerable GetAll();
}
公共类客户
{
公共字符串CustomerName{get;set;}
public int LocationId{get;set;}
公共布尔值{get;set;}
}

此解决方案的唯一问题是类CustomerBydQuery:IQuery,IQuery{public int Id{get;set;}},因为只要我引入一个需要多个参数的查询,公共类CustomerByAndLocationQuery:IQuery,IQuery@jdev4ls这可能看起来很尴尬(使用F#会减少这种尴尬吗?),但这对于处理泛型来说并不是一个坏方法。一些核心的.Net定义使用它,例如
Func
:我没有很好地解释我的意思,我会回答我的问题,这样你就可以知道我在说什么。
interface IQueryDispatcher
{
    IQueryResult<TQueryResult> Dispatch<TQuery, TQueryResult>(IQuery<TQuery, TQueryResult> parms);
}

class GenericQueryDispatcher : IQueryDispatcher
{
  public TQueryResult Dispatch<TQuery, TQueryResult>(IQuery<TQuery, TQueryResult> parms)
  {
    // TODO implement
  }
}
var customerByIdQuery = new CustomerByIdQuery{Id=1};
var customer = _queryDispatcher.Dispatch(customerByIdQuery).Result;
    public interface IQueryDispatcher
  {
    TQueryResult Dispatch<TParameter, TQueryResult>(IQuery<TQueryResult> query)
      where TParameter : IQuery<TQueryResult>
      where TQueryResult : IQueryResult;
  }
  public interface IQueryHandler<in TQuery, out TQueryResult>
    where TQuery : IQuery<TQueryResult>
    where TQueryResult : IQueryResult
  {
    TQueryResult Retrieve(TQuery query);
  }


  public interface IQueryResult { }



  public interface IQuery { }
  public interface IQuery<TQueryResult> : IQuery { }


  public class QueryDispatcher : IQueryDispatcher
  {
    readonly IQueryHandlerRegistry _queryRegistry;

    public QueryDispatcher(IQueryHandlerRegistry queryRegistry)
    {
      _queryRegistry = queryRegistry;
    }

    public TQueryResult Dispatch<TQuery, TQueryResult>(IQuery<TQueryResult> query)
      where TQuery : IQuery<TQueryResult>
      where TQueryResult : IQueryResult
    {
      var handler = _queryRegistry.FindQueryHandlerFor<TQuery, TQueryResult>(query);

       //CANT GET RID OF CAST
      return handler.Retrieve((TQuery)query);
    }
  }

  public interface IQueryHandlerRegistry
  {
    IQueryHandler<TQuery, TQueryResult> FindQueryHandlerFor<TQuery, TQueryResult>(IQuery<TQueryResult> query) 
      where TQuery : IQuery<TQueryResult> 
      where TQueryResult : IQueryResult;
  }

  public class GetCustByIdAndLocQuery : IQuery<CustByIdAndLocQueryResult>
  {
    public string CustName { get; set; }
    public int LocationId { get; set; }

    public GetCustByIdAndLocQuery(string name, int locationId)
    {
      CustName = name;
      LocationId = locationId;
    }
  }

  public class CustByIdAndLocQueryResult : IQueryResult
  {
    public Customer Customer { get; set; }
  }

  public class GetCustByIdAndLocQueryHandler : IQueryHandler<GetCustByIdAndLocQuery, CustByIdAndLocQueryResult>
  {
    readonly ICustomerGateway _customerGateway;

    public GetCustByIdAndLocQueryHandler(ICustomerGateway customerGateway)
    {
      _customerGateway = customerGateway;
    }

    public CustByIdAndLocQueryResult Retrieve(GetCustByIdAndLocQuery query)
    {
      var customer = _customerGateway.GetAll()
                        .SingleOrDefault(x => x.LocationId == query.LocationId && x.CustomerName == query.CustName);

      return new CustByIdAndLocQueryResult() { Customer = customer };
    }
  }

  public interface ICustomerGateway
  {
    IEnumerable<Customer> GetAll();
  }

  public class Customer
  {
    public string CustomerName { get; set; }
    public int LocationId { get; set; }

    public bool HasInsurance { get; set; }
  }