使用枚举参数化对象
我正在使用 C# 和 Unity 依赖注入在 WPF 中开发 MVVM 应用程序。我正在为以下问题寻找最干净的解决方案。
我的一些类是用枚举进行参数化的,例如,我有一个类 AudioChannelViewModel(我们简称为 A),我想注册该类的两个实例,一个用于 Channel.Left,一个用于 Channel.Right。仅此一点并不是问题,因为我通过在 RegisterType 中命名这些实例来注册这些实例,然后稍后通过 [Dependency(name)]
属性引用它们。
此外,A还依赖于其他一些类,我们称它们为Dep1、Dep2和Dep3。为了执行 A 的初始化,我必须拥有所有依赖项以及有关通道的信息。
我尝试使用以下策略:
Dep1、Dep2 和 Dep3 的属性注入,并通过带有 InjectionConstructor 参数的 RegisterType 在构造函数中设置 A 的 Channel。但是我怎么知道 A 何时准备好初始化呢? AFAIK 我无法假设有关属性注入顺序的任何信息。
所有四个项目的构造函数注入。恕我直言,这将是最干净的解决方案,因为我可以在构造函数中执行初始化。但我无法在 Unity 中实现此功能。使用 Channel 的 InjectionConstructor 参数注册 A 会引发异常,并且使用四个 InjectionConstructor 参数注册看起来很难看。
Dep1、Dep2、Dep3的构造函数注入和Channel的属性注入。然后我可以在通道设置器中初始化我的类。它适用于这种情况,但如果 A 由多个属性参数化怎么办?然后我就不知道 A 何时完全构建并准备好初始化。
应该如何进行初始化呢?或者也许我把事情搞得太复杂了。
I'm using C# and Unity Dependency Injection for developing a MVVM application in WPF. I'm looking for a cleanest solution for a following problem.
Some of my classes are parametrized with enums, for example, I have a class AudioChannelViewModel (let's call it for short A) and I want to register two instances of the class, one for Channel.Left and one for Channel.Right. This alone is not a problem, because I register those instances by naming them in RegisterType and then referring to them later by [Dependency(name)]
attribute.
Moreover, A depends on some other classes, lets call them Dep1, Dep2 and Dep3. To perform the initialization of A, I must have ALL of my dependencies and the information about the Channel.
I tried to use the following strategies:
Property injection of Dep1, Dep2 and Dep3 and setting A's Channel in constructor by RegisterType with InjectionConstructor parameter. But how should I know when A is ready to be initialized? AFAIK I cannot assume anything about the property injection order.
Constructor injection of all four items. It would be IMHO the cleanest solution, as I would be able to perform initialization in constructor. But I'm unable to get this working in Unity. Registering A with InjectionConstructor param for Channel throws an exception, and registering with four InjectionConstructor params seems ugly.
Constructor injection of Dep1, Dep2 and Dep3 and property injection of Channel. Then I can initialize my class in the Channel setter. It works for this case, but what if A would be parametrized by more than one property? Then I wouldn't know when A is fully built up and ready for initialization.
How should the initialization be performed? Or maybe I'm making things overly complicated.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您没有确切地说您在策略 #2 中观察到的异常是什么,但这是我将使用的方法(考虑到您能够在成功解决所有依赖项后进行其他初始化的其他要求)。我怀疑问题是您没有为构造函数的所有参数提供“值”...
InjectionConstructor
假设您想要的构造函数是与提供给的值的类型匹配的构造函数注入构造函数
。例如,如果您想为这样的类注册一个构造函数...
您应该这样注册它...
Unity 将使用提供的第一个参数值(
Channel
枚举值),然后解析Dep1
、Dep2
和Dep3
实例。如果存在Dep1
、Dep2
的特定命名实例,您还可以使用ResolvedParameter
作为InjectionConstructor
的参数> 或您需要的Dep3
。仅提供
Channel.Left
或Channel.Right
是不够的,因为 Unity 会认为它被要求使用仅包含Channel
的构造函数争论。或者;如果您已经尝试过但它不起作用...也许 Unity 在这种情况下不支持枚举(双关语)。
此MSDN 页面可能会更加闪耀阐明这个问题。
You don't say exactly what the exception was that you observed in strategy #2, but this is the approach I would be using (given your other requirements for being able to other initialisation having had all the dependencies successfully resolved). I suspect the problem is that you aren't providing a 'value' for all of the arguments of the constructor...
InjectionConstructor
assumes the constructor you want is the one matching the types of the values provided to theInjectionConstructor
.E.g. if you want to register a constructor for such a class...
You should register it thus...
Unity will use the provided value for the first argument (a
Channel
enum value) and will then resolve theDep1
,Dep2
andDep3
instances. You can also useResolvedParameter<T>
as an argument toInjectionConstructor
if there were specific named instances ofDep1
,Dep2
orDep3
that you require.Just providing
Channel.Left
orChannel.Right
alone is insufficient, as Unity will believe it is being asked to use a constructor with just aChannel
argument.Or; if you HAVE already tried that and it isn't working... maybe Unity doesn't support enums in this instance (pun intended).
This MSDN page might shine some more light on the issue.