是否可以从Autofac中解析一个实例,只给出一个字符串键?

时间:2012-02-02 17:21:16

标签: autofac

使用Autofac,可以这样做吗?我没有实例的类型。

var instance = container.Resolve("someStringKey");

从一些谷歌搜索来看,它似乎不可能,但我想确定。

感谢。

1 个答案:

答案 0 :(得分:8)

简短的回答是:不,开箱即用,你必须有类型。

拥有该类型,因为从技术上讲,您可以注册两种不同类型的命名服务:

builder.RegisterInstance(someObject).Named<IFoo>("name-here");
builder.RegisterInstance(someOtherObject).Named<IBar>("name-here");

如果你知道我的意思,如果没有这种类型,你就会“得到你得到的东西”。这是不可预测的。

没有官方支持的方式来获得您正在寻找的东西,但您可能会破解自己的解决方案。像这样:

public static object ResolveUntypedNamed(
  this IComponentContext context,
  string serviceName)
{
  var component = context.ComponentRegistry.Registrations
    .Where(r => r.Services.OfType<KeyedService>()
      .Any(s => s.ServiceKey.Equals(serviceName)))
    .FirstOrDefault();
  return context.ResolveComponent(component, Enumerable.Empty<Parameter>());
}

但是,我不能真的推荐这样做。使Autofac变得灵活的一个原因是能够拥有可以做一些有趣的后期限制的“注册源”。当您以“正确的方式”解析服务时,会进行一些初始化和扫描,以确保需要动态注册的所有内容实际上都是动态注册的。当您访问组件注册表上的注册列表时,它是到那时注册的所有内容的列表,其中可能不包含您正在寻找的命名服务...在这种情况下,您如果不这样做,你的决议就会失败。

如果您没有在应用中使用任何动态注册资料,那么您可能很安全。请注意,你有点像这样的事情,你可能无法获得预期的结果。如果/当奇怪的事情开始发生时,你已被警告

如果您想“以正确的方式”注册和解析无类型服务,您可能需要实现自己的Autofac.Core.Service。键控/命名注册是Autofac.Core.KeyedService但是他们总是有一个相关的类型;您的自定义将不需要键入。然后,您需要在ContainerBuilder上实现自己的注册扩展,以便您可以执行以下操作:

builder.RegisterUntypedNamed(someObject, "name-here");

...然后你还需要IComponentContext上的相应扩展来解析你的服务类型,这样你才能正确地做到:

container.ResolveUntypedNamed("name-here");

...同时仍然参与幕后发布的所有后期注册/扫描内容。