我想根据在运行时传递的输入参数的类型从autofac解析特定的接口实现。
在我的代码中,我有IMyTask<>
的不同实现:
MySillyTask : IMyTask<SillyData>
MyAwesomeTask : IMyTask<AwesomeData>
我像这样注册MyTask<>
的实现:
builder.RegisterAssemblyTypes(typeof (IMyTask<>).Assembly)
.AsClosedTypesOf(typeof (IMyTask<>));
我想使用一个带有注入的Autofac IComponentContext
的类来根据传递的数据类型来解析数据:
public IMyTask<T> GetTask<T>(T input) where T : IData
{
var myTask = _componentContext.Resolve<IMyTask<T>>(); // fails
return myTask;
}
我收到The requested service has not been registered
错误。
如果我尝试将其解析为硬编码的IData
类型,则可以使用:
var myTask = _componentContext.Resolve<IMyTask<SillyData>>(); // works! MySillyTask resolved
我认为这是因为在运行时T
是IData
而不是我传递的特定IData
实现,但有没有办法更改代码以获得我需要的功能?< / p>
编辑: 根据要求提供完整的错误消息:
The requested service 'Whatever.Tasks.IMyTask`1[[Whatever.Inputs.IData, Whatever, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]' has not been registered. To avoid this exception, either register a component to provide the service, check for service registration using IsRegistered(), or use the ResolveOptional() method to resolve an optional dependency.
我如何致电GetTask
:
IData myData = input.MyData;
taskResolver.GetTask(myData);
我想我意识到这是因为T
是IData
而不是导致我的代码失败的实现。虽然我已将我的代码更改为使用命名实例并返回非泛型的IMyTask&#39;我仍然感兴趣,如果我可以使用autofac以我原来的意图解决它。
答案 0 :(得分:2)
我不太了解AutFac,但我认为component.Resolve(...)
有一个接受类型的重载。
我成功地使用Ninject
做了类似的事情 public IMyTask GetTask<T>(T input) where T : IData
{
var taskType = typeof(IMyTask<>);
var inputType = input.GetType();
var genericType = taskType.MakeGenericType(inputType);
return (IMyTask)_componentContext.Resolve(genericType);
}
答案 1 :(得分:1)
您没有提供调用此代码的代码,但我怀疑问题是类型T
基于您调用的代码知道的内容,而不是input
的实际类型。如果调用代码将其称为GetTask<SillyData>(obj);
我怀疑它有效,但我认为您的obj
是IData
恰好是SillyData
。
如果您需要在不事先知道Type的情况下调用泛型方法,则必须使用Reflection。您可以使用input.GetType()
获取真实的基础类型,然后使用MakeGenericType
使ITask<SillyData>
然后MakeGenericMethod
调用Resolve
。
这是另一个堆栈溢出问题,它将向您展示如何通过传递Type参数来调用泛型: