我发现了许多与我面临的问题相似的问题和回答;但我还没能把一个有效的解决方案拼凑起来。
我有以下内容:
public interface IProcessing<V,W> where W: TaskResponse where V: TaskRequest
{
W process(V req);
}
TaskRequest
&amp; TaskResponse
是抽象基类
也定义了这个具体的类:
public class MathProcessor : IProcessing<MathRequest, MathResponse>
{
public MathResponse process(MathRequest req) {
// do stuff
// create a MathResponse instance
return resp;
}
}
MathRequest
&amp; MathResponse
是派生类,各个抽象类用作接口定义中的约束。
根据其界面注册具体类型并使用autofac解析是可以的
但是,在运行时基于另一种类型(在这种情况下是请求对象,例如MathRequest
)尝试解析具体类型的预期用法会产生困难。这基本上是为了实现常见的消息处理程序模式(伪代码跟随),其中接收消息并将其分派给适当的处理程序:
TaskRequest req = getNextRequest();
var proc = container.Resolve(req.getType().Name)
proc.process(req);
基于论坛中的相关主题,基本建议是定义工厂并将其注册到容器,然后在运行时使用工厂根据提供的参数创建我需要的对象。这似乎是正确的。
我也看到了相关的建议,即使用autofac中的IIndex<K,V>
功能按键查找相应的类型/服务。
我无法注册并按密钥解析MathProcessor
类型,其中密钥是一种类型(在本例中为MathRequest
)。该错误可能与通用接口定义和允许的内容更相关。
登记:
builder.RegisterType<MathProcessor>().As<IProcessing<MathRequest, MathResponse>>().Keyed<IProcessing<MathRequest, MathResponse>>(strTypeName);
没问题,但是
builder.RegisterType<MathProcessor>().As<IProcessing<TaskRequest, TaskResponse >>().Keyed<IProcessing< TaskRequest, TaskResponse >>(strTypeName);
不是。
注意:基于泛型类型和co&amp; amp;的所有帖子。 .Net中的逆变我将界面更改为:
public interface IProcessing<in V, out W> where W: TaskResponse where V: TaskRequest
{
W process(V req);
}
但这只是在没有很好理解的情况下猜测。在我的天真视图中,MathProcessor是一种IProcessing,但似乎并非如此。
答案 0 :(得分:9)
我认为这种类型的注册是不可能的,但是,鉴于您似乎以通用方式调用实际处理,我假设您的主要目标是为每种类型的请求实现离散处理器。 / p>
在这种情况下,您可以通过创建BaseProcessing<TV,TW>
类型轻微修改模型。
例如:
public abstract class BaseProcessing<TV, TW> : IProcessing
where TV : TaskRequest
where TW : TaskResponse
{
protected abstract TW DoProcess(TV req);
public TaskResponse Process(TaskRequest req)
{
return DoProcess((TV)req);
}
}
它实现了一个非常基本的IProcessing
接口,即我们将在AutoFac中注册的接口:
public interface IProcessing
{
TaskResponse Process(TaskRequest req);
}
使用它作为基础,您仍然可以创建处理器,例如:
public class MathProcessor : BaseProcessing<MathRequest, MathResponse>
{
protected override MathResponse DoProcess(MathRequest req)
{
return new MathResponse();
}
}
注册它们的一种方法可能是使用键控服务,例如:
builder.RegisterType<MathProcessor>().AsImplementedInterfaces().Keyed<IProcessing>(typeof(MathRequest));
builder.RegisterType<OtherProcessor>().AsImplementedInterfaces().Keyed<IProcessing>(typeof(OtherRequest));
在这种情况下,我实际上并没有使用类型的名称,而是使用类型本身,但两者都可以使用。
现在,拥有键控注册意味着您可以让另一个组件将其作为依赖项使用:
public class SomeConsumer : IConsumer
{
private readonly IIndex<Type, IProcessing> _processors;
public SomeConsumer(IIndex<Type, IProcessing> processors)
{
_processors = processors;
}
public void DoStuff()
{
var someRequest = new MathRequest();
var someResponse = _processors[someRequest.GetType()].Process(someRequest);
}
}