C# Unity:如何在解析另一种类型时指定使用一种类型的特定实例

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/618038/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 10:27:05  来源:igfitidea点击:

Unity: how to specify to use specific instance of a type when resolving another type

c#.netunity-container

提问by

I'm trying the following in Unity:

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

I have a type with the following constructor

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

public Type1(Type2 firstDependency, Type3 secondDependency)

When resolving Type1using Unity, I want to specify the specific instance for Type2to inject. This specific instance of Type2is not registered in the container. Type3is registered in the container and should be resolved as usual.

Type1使用 Unity解析时,我想指定Type2要注入的特定实例。此特定实例Type2未在容器中注册。Type3在容器中注册,应该像往常一样解决。

To be more specific, consider Type1is a DocumentViewerclass. Type2is a specific Document. Type3is a SpellingChecker.

更具体地说,考虑Type1是一个DocumentViewer类。Type2是一个特定的Document. Type3是一个SpellingChecker

I want to be able to resolve DocumentViewerfor a Documentthat is only known at runtime. Multiple DocumentViewerinstances for differenct Documentscan be created.

我希望能够解决DocumentViewer一个Document只在运行时已知的问题。可以创建DocumentViewer不同的多个实例Documents

How can I do this?

我怎样才能做到这一点?

回答by REA_ANDREW

Here is a quick example I have made, you use RegisterInstance or you can use a Lifetime management Claas

这是我制作的一个简单示例,您可以使用 RegisterInstance 或者您可以使用 Lifetime 管理 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;
    }
}

Update:I included a type with two parameters in constructor to show it can also be resolved.

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

回答by Alexander

Try using named instances:

尝试使用命名实例:


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");
}


You can do some checks on type 1 and decide which instance of type 2 you will need. Note that the "new ContainerControlledLifetimeManager()" parameter will initialize a singleton instance of the resisted type, so you will always get the same instance of type 2.

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

Update:Same with interfaces. Hope this helps.

更新:与接口相同。希望这可以帮助。


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();

回答by Alexander

If you have a class with multiple constructors, you can decide which constructor is used by the Unity container using the "InjectionConstructor" attribute. This gives you the possibility to set some parameters manually.

如果您有一个具有多个构造函数的类,您可以使用“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)
    {
    }
}

回答by Ray Henry

Use a factory.

使用工厂。

public class Type1Factory
{
  private Type3 type3;

  public Type1Factory(Type3 _type3)
  {
     type3 = _type3;
  }

  public GetType1(Type2 type2)
  {
    return new Type1(type2, type3);
  }
}

Call it this way:

这样称呼它:

// 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());

This assumes that you are only trying to use Unity to resolve the Type3 dependency, and that you have no control over the constructors in Type1. If you can edit Type1, use Alexader R.'s suggestion to make Unity only resolve the one parameter constructor.

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

回答by Dmitrii Lobanov

You can use container hierarchy, please read my answer for similar question here: Microsoft Unity. How to specify a certain parameter in constructor?.

您可以使用容器层次结构,请在此处阅读我对类似问题的回答:Microsoft Unity。如何在构造函数中指定某个参数?.

The only difference is that looks like you should use RegisterInstance()in your child container instead of RegisterType(). And maybe not, it depends on whether you created instance before somewhere outside of your code or not.

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