使用Autofac,可以这样做吗?我没有实例的类型。
var instance = container.Resolve("someStringKey");
从一些谷歌搜索来看,它似乎不可能,但我想确定。
感谢。
答案 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");
...同时仍然参与幕后发布的所有后期注册/扫描内容。