尝试基于autofac中在运行时传递的泛型类型来解析接口实现

时间:2014-04-25 14:12:04

标签: c# generics autofac

我想根据在运行时传递的输入参数的类型从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

我认为这是因为在运行时TIData而不是我传递的特定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);

我想我意识到这是因为TIData而不是导致我的代码失败的实现。虽然我已将我的代码更改为使用命名实例并返回非泛型的IMyTask&#39;我仍然感兴趣,如果我可以使用autofac以我原来的意图解决它。

2 个答案:

答案 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);我怀疑它有效,但我认为您的objIData恰好是SillyData

如果您需要在不事先知道Type的情况下调用泛型方法,则必须使用Reflection。您可以使用input.GetType()获取真实的基础类型,然后使用MakeGenericType使ITask<SillyData>然后MakeGenericMethod调用Resolve

这是另一个堆栈溢出问题,它将向您展示如何通过传递Type参数来调用泛型:

<强> How do I use reflection to call a generic method?