使用 Autofac 创建运行时类型的实例。

4

我目前有一个通过反射获取的运行时类型。我需要创建此类型的实例,因此我使用Activator类,如下所示:

(T)Activator.CreateInstance(instance)

我在我的应用程序中使用Autofac作为我的IoC并使用DI。不幸的是,我无法在这些实例中使用DI,因为当我尝试通过构造函数注入它们时,Activator类无法解析依赖项。是否有一种Autofac方法可以做到这一点,但使用我的Autofac注册来解决依赖关系呢?谢谢。
1个回答

4
我认为您有几个选择,通常情况下,Autofac需要在容器内部具有类型才能解析它。
最简单和直接的解决方案是注册类型。如果您在构建容器时有一个对Type的引用,您可以使用它来向Autofac注册并解析它。
Type customType = GetTheRuntimeType();
var builder = new ContainerBuilder();
builder.RegisterType(customType);

你可以在此基础上添加更多内容(例如InstancePerLifetimeScope()As<IInterface>()等),但这样就可以工作了。 如果在构建容器时没有该类型,则可以选择在事后手动注入属性。 这有点像服务定位,但这意味着您可以将类型创建与其它操作分开。
Type customType = GetTheRuntimeType();
var builder = new ContainerBuilder();
// register everything else, then
var container = builder.Build();
using(var scope = container.BeginLifetimeScope())
{
  var instance = Activator.CreateInstance(customType);
  scope.InjectUnsetProperties(instance);
}

这不应该是构造函数注入,而应该是属性注入。但它非常容易。第三个选项是最集成的,但可能也是最困难的。你可以实现注册源,告诉Autofac有关你的类型的信息。我不会在这里放置代码,因为它有很多内容,而且我没有编译器,但是请阅读文档并查看示例。文档中有示例。这就是Autofac动态处理像IEnumerable<T>这样的东西的方式,即当您从未显式地注册时。您可以提供任何一组运行时类型,并且所有这些类型都可以使用注册源动态插入到容器中。
如果您有能力执行第一个选项并只是注册类型,我建议您这样做。这是实现良好集成的最简单方法。
属性注入很有效,但它有点麻烦。这取决于您的解决方案需要存在多长时间或者您只需要快速使其工作。
注册源解决方案绝对是最强大的。如果在创建容器之前没有运行时类型,则这是最佳选择。虽然在一开始时更难以使用,但它将更具扩展性,因为您可以利用它来满足任何额外的运行时类型需求。无论您做什么,都不要使用Update()在构建容器后添加注册。它已经被标记为过时了一年左右,并且将被淘汰。它不能作为长期解决方案。

我知道编译时的类型,因此可以提前注册这些类型。我的问题是关于解析运行时类型的。这就是我最终所做的:return (T)scope.Resolve(instance); - odannyc
抱歉,我想我误读了问题。听起来好像你在将类型放入Autofac中遇到了问题。你找到的解决方法绝对是注册后取回它的方式。 - Travis Illig
是的,我之前认为 Resolve 只是一个泛型,需要传递一个具体的类型参数,例如: Resolve<SomeClass>()。但实际上我们也可以通过传递一个类型来进行解析,类似这样:Resolve(runtimeType) - odannyc

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接