【问题标题】:Unity: how to specify to use specific instance of a type when resolving another typeUnity:如何在解析另一种类型时指定使用类型的特定实例
【发布时间】:2010-10-11 17:00:02
【问题描述】:

我正在 Unity 中尝试以下操作:

我有一个具有以下构造函数的类型

public Type1(Type2 firstDependency, Type3 secondDependency)

使用Unity解析Type1时,我想指定Type2注入的具体实例。 Type2 的这个特定实例未在容器中注册。 Type3 已在容器中注册,应照常解决。

更具体地说,考虑Type1 是一个DocumentViewer 类。 Type2 是特定的 DocumentType3SpellingChecker

我希望能够将DocumentViewer 解析为仅在运行时才知道的Document。可以为不同的Documents 创建多个DocumentViewer 实例。

我该怎么做?

【问题讨论】:

  • 抱歉,我仍然不明白为什么无法使用以下答案中给出的代码解析文档视图的实例。什么是“文档仅在运行时才知道”?如果您不知道文档实例的确切类型,请考虑使用接口。
  • 换一种说法:我想解析一个类型,但是只让容器自己解析一些依赖。我想自己提供其他实例。

标签: c# .net unity-container


【解决方案1】:

这是我制作的一个简单示例,您使用 RegisterInstance 或者您可以使用 Lifetime management Claas

static void Main(string[] args)
{
    IUnityContainer container = new UnityContainer();

    container.RegisterType<Type1>();

    container.RegisterInstance<Type2>(new Type2());

    Type1 t = container.Resolve<Type1>();

    Type2 t2 = container.Resolve<Type2>();

    Type3 t3 = container.Resolve<Type3>();

    Console.ReadKey();
}

public class Type1
{
}

public class Type2
{
}

public class Type3
{
    private Type1 t;
    private Type2 t2;
    public Type3(Type1 t, Type2 t2)
    {
        this.t = t;
        this.t2 = t2;
    }
}

更新:我在构造函数中包含了一个带有两个参数的类型,以表明它也可以被解析。

【讨论】:

    【解决方案2】:

    尝试使用命名实例:

    IUnityContainer container = new UnityContainer(); container.RegisterType<Type1>(); container.RegisterType<Type2>("Instance 1", new ContainerControlledLifetimeManager()); container.RegisterType<Type2>("Instance 2", new ContainerControlledLifetimeManager()); container.RegisterType<Type3>(); Type1 type1 = container.Resolve<Type1>(); if (type1 == ...) { Type2 instance1 = container.Resolve<Type2>("Instance 1"); } else { Type2 instance2 = ontainer.Resolve<Type2>("Instance 2"); }

    您可以对类型 1 进行一些检查并决定您需要哪个类型 2 的实例。请注意,“new ContainerControlledLifetimeManager()”参数将初始化被抵抗类型的单例实例,因此您将始终获得相同的类型 2 实例。

    更新:与接口相同。希望这会有所帮助。

    IUnityContainer container = new UnityContainer(); container.RegisterType<TextDocument>(); container.RegisterType<ImageDocument>(); container.RegisterType(typeof (IView), typeof (TextView), "Text", new ContainerControlledLifetimeManager()); container.RegisterType(typeof (IView), typeof (ImageView), "Image", new ContainerControlledLifetimeManager()); IDocument document = container.Resolve<TextDocument>(); IView view = null; if (document is TextDocument) { view = container.Resolve<IView>("Text"); } else { view = container.Resolve<IView>("Image"); } view.Show();

    【讨论】:

    • RegisterInstance 也实现了单例效果
    【解决方案3】:

    如果您有一个具有多个构造函数的类,您可以使用“InjectionConstructor”属性来决定 Unity 容器使用哪个构造函数。这使您可以手动设置一些参数。

    public class Test { public Test() { } // Always use the following constructor [InjectionConstructor] public Test(Type1 type1) : this() { } public Test(Type1 type1, Type2 type2) : this(type1) { } }

    【讨论】:

      【解决方案4】:

      使用工厂。

      public class Type1Factory
      {
        private Type3 type3;
      
        public Type1Factory(Type3 _type3)
        {
           type3 = _type3;
        }
      
        public GetType1(Type2 type2)
        {
          return new Type1(type2, type3);
        }
      }
      

      这样称呼:

      // SpellingChecker is subclass of Type3
      IUnityContainer container = new UnityContainer();
      container.RegisterType<Type3>(typeof(SpellingChecker));
      
      // DocumentViewer is subclass of Type2
      Type1Factory factory = container.Resolve<Type1Factory>();
      Type1 type1 = factory.GetType1(new DocumentViewer());
      

      这假设您只是尝试使用 Unity 来解决 Type3 依赖项,并且您无法控制 Type1 中的构造函数。如果您可以编辑 Type1,请使用 Alexader R. 的建议使 Unity 仅解析一个参数构造函数。

      【讨论】:

        【解决方案5】:

        您可以使用容器层次结构,请在此处阅读我对类似问题的回答:Microsoft Unity. How to specify a certain parameter in constructor?

        唯一的区别是您应该在子容器中使用RegisterInstance() 而不是RegisterType()。也许不是,这取决于您是否在代码之外的某个地方创建了实例。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-12-09
          • 2018-11-21
          相关资源
          最近更新 更多