使用枚举参数化对象

发布于 2024-11-07 17:18:12 字数 860 浏览 2 评论 0原文

我正在使用 C# 和 Unity 依赖注入在 WPF 中开发 MVVM 应用程序。我正在为以下问题寻找最干净的解决方案。

我的一些类是用枚举进行参数化的,例如,我有一个类 AudioChannelViewModel(我们简称为 A),我想注册该类的两个实例,一个用于 Channel.Left,一个用于 Channel.Right。仅此一点并不是问题,因为我通过在 RegisterType 中命名这些实例来注册这些实例,然后稍后通过 [Dependency(name)] 属性引用它们。

此外,A还依赖于其他一些类,我们称它们为Dep1、Dep2和Dep3。为了执行 A 的初始化,我必须拥有所有依赖项以及有关通道的信息。

我尝试使用以下策略:

  1. Dep1、Dep2 和 Dep3 的属性注入,并通过带有 InjectionConstructor 参数的 RegisterType 在构造函数中设置 A 的 Channel。但是我怎么知道 A 何时准备好初始化呢? AFAIK 我无法假设有关属性注入顺序的任何信息。

  2. 所有四个项目的构造函数注入。恕我直言,这将是最干净的解决方案,因为我可以在构造函数中执行初始化。但我无法在 Unity 中实现此功能。使用 Channel 的 InjectionConstructor 参数注册 A 会引发异常,并且使用四个 InjectionConstructor 参数注册看起来很难看。

  3. 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:

  1. 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.

  2. 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.

  3. 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 技术交流群。

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

发布评论

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

评论(1

过气美图社 2024-11-14 17:18:12

您没有确切地说您在策略 #2 中观察到的异常是什么,但这是我将使用的方法(考虑到您能够在成功解决所有依赖项后进行其他初始化的其他要求)。我怀疑问题是您没有为构造函数的所有参数提供“值”... InjectionConstructor 假设您想要的构造函数是与提供给的值的类型匹配的构造函数注入构造函数

例如,如果您想为这样的类注册一个构造函数...

public class AudioChannelViewModel {
  public AudioChannelViewModel(Channel channel, Dep1 dep1, Dep2 dep2, Dep3 dep3) {
    ...
  }
}

您应该这样注册它...

container.RegisterType<AudioChannelViewModel>("left", 
    new InjectionConstructor(Channel.Left,
      typeof(Dep1), typeof(Dep2), typeof(Dep3)));
container.RegisterType<AudioChannelViewModel>("right", 
    new InjectionConstructor(Channel.Right,
      typeof(Dep1), typeof(Dep2), typeof(Dep3)));

Unity 将使用提供的第一个参数值(Channel 枚举值),然后解析Dep1Dep2Dep3 实例。如果存在 Dep1Dep2 的特定命名实例,您还可以使用 ResolvedParameter 作为 InjectionConstructor 的参数> 或您需要的 Dep3

仅提供 Channel.LeftChannel.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 the InjectionConstructor.

E.g. if you want to register a constructor for such a class...

public class AudioChannelViewModel {
  public AudioChannelViewModel(Channel channel, Dep1 dep1, Dep2 dep2, Dep3 dep3) {
    ...
  }
}

You should register it thus...

container.RegisterType<AudioChannelViewModel>("left", 
    new InjectionConstructor(Channel.Left,
      typeof(Dep1), typeof(Dep2), typeof(Dep3)));
container.RegisterType<AudioChannelViewModel>("right", 
    new InjectionConstructor(Channel.Right,
      typeof(Dep1), typeof(Dep2), typeof(Dep3)));

Unity will use the provided value for the first argument (a Channel enum value) and will then resolve the Dep1, Dep2 and Dep3 instances. You can also use ResolvedParameter<T> as an argument to InjectionConstructor if there were specific named instances of Dep1, Dep2 or Dep3 that you require.

Just providing Channel.Left or Channel.Right alone is insufficient, as Unity will believe it is being asked to use a constructor with just a Channel 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文