【发布时间】:2012-01-03 12:30:34
【问题描述】:
我在 Autofac 注册了 多个(通用)类型,所有类型都“实现”了一个(通用)标记接口。基本上这是注册,我不能更改它(例如命名):
builder.RegisterGeneric(typeof(MyType1<>)).As(typeof(IMarkerInterface<>));
builder.RegisterGeneric(typeof(MyType2<>)).As(typeof(IMarkerInterface<>));
builder.RegisterGeneric(typeof(MyType3<>)).As(typeof(IMarkerInterface<>));
其中 builder 是一个 ContainerBuilder 实例。 如果我只知道实现的(类型)名称(例如 MyAssembly.MyType2),是否有解决注册为 IMarkerInterface 的类型的正确方法? 注册可以简单地从带有 LINQ 查询的 IComponentContext.ComponentRegistry.Registrations 中选择,所以最后我也有注册对象,只是无法激活它:
- registration.Activator.ActivateInstance() 需要构造函数参数,但我不知道这些(虽然如果解决了它们可以通过Autofac注入)
- used to be a method 完全适合我(因为我有注册 id 和 ICompontentContext 实例),但现在 (v2.5.2.830) 似乎没有了。
- 由于该类型的 Service 类型是标记接口,因此我无法按服务类型解析,因为它会解析恰好位于顶部的一个实现。
我认为一种解决方法是使用从 IMarkerInterface 派生的接口来标记类型,因此它们也都将具有独特的服务。另一种方法是解决 IEnumerable>,但这将解决所有实现,而不仅仅是所需的实现(尽管这对性能的影响可以忽略不计,但它仍然是多余的)。但是我不知道这是否是最好的解决方案,我觉得应该有更直接的方法。
任何帮助将不胜感激!
解决方案
因为我还不能回答,这里: 只是模仿 Autofac.ResolutionExtensions 曾经的实现,这段代码可以工作(坦率地说,我不知道为什么:构造函数参数被正确填充;这应该意味着我误解了“参数”参数是什么)。
registration.Activator.ActivateInstance(_componentContext, Enumerable.Empty<Parameter>());
registration 是 IComponentRegistration 实例,对应于我要实例化的实现。 显然,这也需要使用当前类型参数“初始化”容器。来电
_componentContext.IsRegistered<IMarkerInterface<TypeParameter>>()
够了。
感谢 Sebastien Weber 和 kvalcanti 的投入!
【问题讨论】:
-
您注册了一个开放的仿制药,现在您想做...究竟是什么? AutoFac 将为您关闭类型定义(即,如果请求 IMarkerInterfac
,它将为您提供 MyType 的实例。这种行为有什么问题? -
我已经澄清了这个问题;抱歉,不清楚有多个实现(实现相同的标记接口),我想选择一个来解决(在运行时)。
-
我不是 AutoFac 方面的专家,但据我了解,上述方法永远不会奏效。您为同一个(同样开放的)泛型目标接口注册了多个开放的泛型类型。当其他容器被要求提供(任何关闭的)类型 IMarkerInterface
的实例时,它们只会使用最后一次注册 (MyType3)。我认为 AutoFac 会做类似的事情。 -
Autofac 似乎比这聪明得多,请参阅解决方案 :-)。
-
IComponentContext.ResolveComponent() 是替换您提到的 IIRC 的方法。但是,您的问题似乎仍然缺少一些信息-您何时关闭泛型类型? IE。在 IMarkerInterface
? 中指定 Foo
标签: c# dependency-injection autofac