解析 IEnumerable团结一致

发布于 2024-08-16 05:51:34 字数 706 浏览 2 评论 0原文

Unity 可以自动解析 IEnumerable 吗?

假设我有一个带有此构造函数的类:

public CoalescingParserSelector(IEnumerable<IParserBuilder> parserBuilders)

并且我在容器中配置了单独的 IParserBuilder 实例:

container.RegisterType<IParserSelector, CoalescingParserSelector>();
container.RegisterType<IParserBuilder, HelpParserBuilder>();
container.RegisterType<IParserBuilder, SomeOtherParserBuilder>();

我可以在不必实现 IEnumerable 的自定义实现的情况下完成这项工作吗?

var selector = container.Resolve<IParserSelector>();

到目前为止,我还无法以任何简单的方式表达这一点,但我仍在加强 Unity,所以我可能错过了一些东西。

Can Unity automatically resolve IEnumerable<T>?

Let's say I have a class with this constructor:

public CoalescingParserSelector(IEnumerable<IParserBuilder> parserBuilders)

and I configure individual IParserBuilder instances in the container:

container.RegisterType<IParserSelector, CoalescingParserSelector>();
container.RegisterType<IParserBuilder, HelpParserBuilder>();
container.RegisterType<IParserBuilder, SomeOtherParserBuilder>();

can I make this work without having to implement a custom implementation of IEnumerable<IParserBuilder>?

var selector = container.Resolve<IParserSelector>();

So far I haven't been able to express this in any simple way, but I'm still ramping up on Unity so I may have missed something.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

小ぇ时光︴ 2024-08-23 05:51:34

事实证明,这实际上非常简单:

container.RegisterType<IEnumerable<IParserBuilder>, IParserBuilder[]>();

Unity 本身就理解数组,因此我们只需将可枚举映射到相同类型的数组即可。

It turns out that this is actually awfully simple to do:

container.RegisterType<IEnumerable<IParserBuilder>, IParserBuilder[]>();

Unity natively understands arrays, so we just need to map the enumerable to an array of the same type.

暖树树初阳… 2024-08-23 05:51:34

@Metro Smurf:你的回答让我走上了正轨:Unity 无法自动解析 IEnumerable 依赖项。

我无法编译您的示例,因为 RegisterType 方法不采用 InjectionConstructor 实例作为参数。

另请注意,仅当您使用不同名称注册了多个类型时,ResolveAll 方法才有效,并且此方法不会返回默认(未命名)注册的实例。 (顺便说一句,我完全不同意这种行为)。

这对我有用:

container.RegisterType<IParserBuilder, HelpParserBuilder>("HelpParserBuilder");
container.RegisterType<IParserBuilder, SomeOtherParserBuilder>("SomeOtherParserBuilder");
container.RegisterType<IParserSelector, CoalescingParserSelector>();

container.Configure<InjectedMembers>().ConfigureInjectionFor<CoalescingParserSelector>(new InjectionConstructor(container.ResolveAll<IParserBuilder>()));

为了解析单个实例,您还需要添加默认注册,否则对 Resolve() 的调用将失败。

此代码使默认注册启用单一分辨率:

container.RegisterType<IParserBuilder, HelpParserBuilder>();
IParserBuilder builder = container.Resolve<IParserBuilder>()

@Metro Smurf: your answer got me in the right track: Unity is unable to automatically resolve IEnumerable<T> dependencies.

I wasn't able to compile your example since the RegisterType method doesn't take an InjectionConstructor instance as parameter.

Also note that the ResolveAll method will only work if you've registered multiple types with different names and also this method does NOT return an instance for the default (unnamed) registration. (I completely disagree with this behavior btw).

This is what worked for me:

container.RegisterType<IParserBuilder, HelpParserBuilder>("HelpParserBuilder");
container.RegisterType<IParserBuilder, SomeOtherParserBuilder>("SomeOtherParserBuilder");
container.RegisterType<IParserSelector, CoalescingParserSelector>();

container.Configure<InjectedMembers>().ConfigureInjectionFor<CoalescingParserSelector>(new InjectionConstructor(container.ResolveAll<IParserBuilder>()));

In order to resolve a single instance you will need to also add a default registration otherwise the call to Resolve<T>() will fail.

This code makes the default registration to enable single resolution:

container.RegisterType<IParserBuilder, HelpParserBuilder>();
IParserBuilder builder = container.Resolve<IParserBuilder>()
累赘 2024-08-23 05:51:34

如果你想普遍支持 IEnumerable,那么你可以添加这一行:

_container.RegisterType(typeof(IEnumerable<>), new InjectionFactory((IUnityContainer container, Type type, string name) => container.ResolveAll(type.GetGenericArguments().Single())));

This is he generic version of

container.RegisterType<IEnumerable<IParserBuilder>, IParserBuilder[]>();

If you want to generally support IEnumerable, then you can add this line:

_container.RegisterType(typeof(IEnumerable<>), new InjectionFactory((IUnityContainer container, Type type, string name) => container.ResolveAll(type.GetGenericArguments().Single())));

This is he generic version of

container.RegisterType<IEnumerable<IParserBuilder>, IParserBuilder[]>();
蓝眼泪 2024-08-23 05:51:34

我相信您需要使用 ResolveAll 方法并使用显式InjectionConstructor 对象,即:

container.RegisterType<IParserBuilder, HelpParserBuilder>();
container.RegisterType<IParserBuilder, SomeOtherParserBuilder>();

var injectedBuilders = new InjectionConstructor(container.ResolveAll<IParserBuilder>());
container.RegisterType<IParserSelector, CoalescingParserSelector>(injectedBuilders);

换句话说,我不认为Unity能够自动解析类型的所有实例,并知道在具有 IEnumerable 参数的类上使用构造函数注入,而无需显式声明 InjectionConstructor 对象位于运行时< /a>.

当然,我还在学习 Unity,但这就是我的经验 (YMMV)。

I believe you'll need to use the ResolveAll method and use an explicit InjectionConstructor object, i.e.:

container.RegisterType<IParserBuilder, HelpParserBuilder>();
container.RegisterType<IParserBuilder, SomeOtherParserBuilder>();

var injectedBuilders = new InjectionConstructor(container.ResolveAll<IParserBuilder>());
container.RegisterType<IParserSelector, CoalescingParserSelector>(injectedBuilders);

In other words, I don't think Unity is able to automatically resolve all instances of a type and know to use constructor injection on a class with an IEnumerable parameter without an explicitly declaring an InjectionConstructor object at Run Time.

Granted I'm still learning Unity as well, but this has been my experience (YMMV).

金橙橙 2024-08-23 05:51:34

对我有用

container.RegisterType<IEnumerable<IParserBuilder>, IParserBuilder[]>();

的只是记住,当您向容器注册 IParserBuilder 类型时,需要唯一的名称,否则它将始终是一个空数组。所以使用

container.RegisterType<IParserBuilder, RealParserBuilder>("UniqueName");

The

container.RegisterType<IEnumerable<IParserBuilder>, IParserBuilder[]>();

Worked for me only keep in mind that when you register IParserBuilder types with your container an unique name is required otherwise it will Always be an empty array. So use

container.RegisterType<IParserBuilder, RealParserBuilder>("UniqueName");
童话里做英雄 2024-08-23 05:51:34

截至 2010 年 5 月,已有对此的原生支持。请查看此处

As of May 2010, there is the native support for that. Check it out here.

断舍离 2024-08-23 05:51:34

我这样做了

        container.RegisterTypes(
            AllClasses.FromLoadedAssemblies().
                Where(type => typeof(IParserBuilder).IsAssignableFrom(type)),
            WithMappings.FromAllInterfaces,
            WithName.TypeName,
            WithLifetime.Transient);

        container.RegisterType<IEnumerable<IParserBuilder>, IParserBuilder[]>();

,它注册了实现 IParserBuilder 的所有内容,因此当您添加新的时,无需添加任何其他代码即可使其出现在构建器列表中。

I did this like so

        container.RegisterTypes(
            AllClasses.FromLoadedAssemblies().
                Where(type => typeof(IParserBuilder).IsAssignableFrom(type)),
            WithMappings.FromAllInterfaces,
            WithName.TypeName,
            WithLifetime.Transient);

        container.RegisterType<IEnumerable<IParserBuilder>, IParserBuilder[]>();

Which registers everything that implements IParserBuilder, so when you add a new one you don't need to add any other code for it to appear in the list of builders.

走野 2024-08-23 05:51:34

你可以这样做:

container.RegisterType<IParserBuilder, HelpParserBuilder>("HelpParser");
container.RegisterType<IParserBuilder, SomeOtherParserBuilder>("SomeOtherParser");

container.RegisterType<IParserSelector, CoalescingParserSelector>(
 new InjectionConstructor(
                    new ResolvedArrayParameter<IParserBuilder>(
                        new ResolvedParameter<IParserBuilder>("HelpParser"),
                        new ResolvedParameter<IParserBuilder>("SomeOtherParser")
                    )
));

You can do like this:

container.RegisterType<IParserBuilder, HelpParserBuilder>("HelpParser");
container.RegisterType<IParserBuilder, SomeOtherParserBuilder>("SomeOtherParser");

container.RegisterType<IParserSelector, CoalescingParserSelector>(
 new InjectionConstructor(
                    new ResolvedArrayParameter<IParserBuilder>(
                        new ResolvedParameter<IParserBuilder>("HelpParser"),
                        new ResolvedParameter<IParserBuilder>("SomeOtherParser")
                    )
));
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文