Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/275.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 没有从…的隐式引用转换。。。通用查询处理程序cqrs_C#_Asp.net Mvc_Asp.net Core_Domain Driven Design_Cqrs - Fatal编程技术网

C# 没有从…的隐式引用转换。。。通用查询处理程序cqrs

C# 没有从…的隐式引用转换。。。通用查询处理程序cqrs,c#,asp.net-mvc,asp.net-core,domain-driven-design,cqrs,C#,Asp.net Mvc,Asp.net Core,Domain Driven Design,Cqrs,我想创建一个通用的查询处理程序(将来还有命令处理程序),它可以处理每个查询,并在处理后返回查询结果 IQueryHandler接口: public interface IQueryHandler { } public interface IQueryHandler<TResult> : IQueryHandler { TResult Execute(); } public interface IQueryHandler<TQuery, TResult> :

我想创建一个通用的查询处理程序(将来还有命令处理程序),它可以处理每个查询,并在处理后返回查询结果

IQueryHandler接口:

public interface IQueryHandler
{

}

public interface IQueryHandler<TResult> : IQueryHandler
{
    TResult Execute();
}

public interface IQueryHandler<TQuery, TResult> : IQueryHandler
    where TResult : class 
    where TQuery: class
{
    TResult Execute(TQuery query);
}
简单查询对象:

public class BrowseTitlesQuery : IQuery
{
    public string Title { get; set; }
}
简单查询处理程序对象:

public class BrowseTitlesQueryHandler : IQueryHandler<BrowseTitlesQuery, IEnumerable<string>>
{
    public IEnumerable<string> Execute(BrowseTitlesQuery query)
    {
        throw new System.NotImplementedException();
    }
}
public类BrowseTitlesQueryHandler:IQueryHandler
{
公共IEnumerable执行(BrowseTitlesQuery查询)
{
抛出新系统。NotImplementedException();
}
}
克雷布斯

public class QueryBus
{
    public object Resolve<T>(IQuery query) 
        where T: IQueryHandler<IQuery, Object>, IQueryHandler, new()
    {
        return new T().Execute(query);
    }
}
公共类查询总线
{
公共对象解析(IQuery查询)
其中T:iqeryHandler,iqeryHandler,new()
{
返回新的T()。执行(查询);
}
}
当然还有Program.cs类(我正在使用控制台应用程序进行测试)

类程序
{
静态void Main(字符串[]参数)
{
var-bus=新的QueryBus();
var query=new BrowseTitlesQuery();
总线解析(查询);
}
}
在我看来,它应该是有效的,但它不是。 我有以下错误:

类型“cqrs.BrowseTitlesQueryHandler”不能用作泛型类型或方法“QueryBus.Resolve(IQuery)”中的类型参数“T”。没有从“cqrs.BrowseTitlesQueryHandler”到“cqrs.IQueryHandler”的隐式引用转换。[cqrs]

为什么呢

您在这里遇到了问题

让我们先看一下协方差:
BrowseTitlesQueryHandler
实现了
IQueryHandler
,因此
Execute
的返回值是
IEnumerable
。但是,在
QueryBus
中,您需要
T
IQueryHandler
,返回值为
object

为了允许
IQueryHandler
向下转换为
IQueryHandler
TResult
参数需要是协变的。这在这里非常简单,因为它实际上是一个结果,所以使it协变是正确的做法(注意
out
):

现在,
BrowseTitlesQueryHandler
获得了正确的查询参数并可以正确执行。当然,您需要调整通话,然后:

bus.Resolve<BrowseTitlesQueryHandler, BrowseTitlesQuery>(query);
总线解析(查询);
您在这里遇到问题

让我们先看一下协方差:
BrowseTitlesQueryHandler
实现了
IQueryHandler
,因此
Execute
的返回值是
IEnumerable
。但是,在
QueryBus
中,您需要
T
IQueryHandler
,返回值为
object

为了允许
IQueryHandler
向下转换为
IQueryHandler
TResult
参数需要是协变的。这在这里非常简单,因为它实际上是一个结果,所以使it协变是正确的做法(注意
out
):

现在,
BrowseTitlesQueryHandler
获得了正确的查询参数并可以正确执行。当然,您需要调整通话,然后:

bus.Resolve<BrowseTitlesQueryHandler, BrowseTitlesQuery>(query);
总线解析(查询);

您必须在查询总线上扩展类型参数:

public class QueryBus
{
    public object Resolve<THandler, TQuery, TResult>(TQuery query) 
        where T: IQueryHandler<TQuery, TResult>, IQueryHandler, new()
        where TResult : class 
        where TQuery: class
    {
        return new THandler().Execute(query);
    }
}
公共类查询总线
{
公共对象解析(TQuery查询)
其中T:iqeryHandler,iqeryHandler,new()
结果:在哪里上课
提问:课堂
{
返回新的THandler().Execute(query);
}
}
然后像这样称呼它:

bus.Resolve<BrowseTitlesQueryHandler, BrowseTitlesQuery, IEnumerable<string>>(query);
总线解析(查询);

您必须在查询总线上扩展类型参数:

public class QueryBus
{
    public object Resolve<THandler, TQuery, TResult>(TQuery query) 
        where T: IQueryHandler<TQuery, TResult>, IQueryHandler, new()
        where TResult : class 
        where TQuery: class
    {
        return new THandler().Execute(query);
    }
}
公共类查询总线
{
公共对象解析(TQuery查询)
其中T:iqeryHandler,iqeryHandler,new()
结果:在哪里上课
提问:课堂
{
返回新的THandler().Execute(query);
}
}
然后像这样称呼它:

bus.Resolve<BrowseTitlesQueryHandler, BrowseTitlesQuery, IEnumerable<string>>(query);
总线解析(查询);

为什么有3个名为“IQueryHandler”的接口?仅用于测试,最后我希望只有一个接口,它将是上面列表中的第三个。如果重构并只留下第三个接口?不会发生任何情况,同样的错误。为什么有3个名为“IQueryHandler”的接口?仅用于测试,最后,我希望只有一个接口,它将是上述列表中的第三个接口。如果重构并只保留第三个接口,则不会发生任何情况,同样的错误。它可以工作,但我希望避免将查询类型作为第二个T参数传递。如果没有第二个泛型参数,就没有其他方法可以实现它,不是吗?如果您需要查询处理程序来处理确切的类型(而不仅仅是
IQuery
),就没有这种方法了。您可以做的(如果您的应用程序允许的话)是将
QueryBus
设置为泛型,将处理程序作为类型参数,然后仅将查询类型作为
Resolve
的参数。这样您就可以执行
newquerybus().Resolve(query)
(编译器将使用类型推断提供泛型查询类型参数)。但这当然会将您的查询总线限制为单个处理程序类型,因此它可能不是您所需要的。此时,我仅使用“new”运算符创建查询处理程序,但我认为它不是那么优雅,所以我想将实例的逻辑移到查询总线。如果我使用通用查询总线,我将不得不通过新操作符创建QueryBus的实例,因此我认为,您提出的第一个解决方案更好。它可以工作,但我希望避免将查询类型作为第二个T参数传递。如果没有第二个泛型参数,就没有其他方法可以实现它,不是吗?如果您需要查询处理程序来处理确切的类型(而不仅仅是
IQuery
),就没有这种方法了。您可以做的(如果您的应用程序允许的话)是将
QueryBus
设置为泛型,将处理程序作为类型参数,然后仅将查询类型作为
Resolve
的参数。这样您就可以执行
newquerybus().Resolve(query)
(编译器将使用类型推断提供泛型查询类型参数)。但这当然会限制你的行为
bus.Resolve<BrowseTitlesQueryHandler, BrowseTitlesQuery, IEnumerable<string>>(query);