覆盖依赖链

时间:2015-12-24 08:29:35

标签: c# dependency-injection unity-container

我是Unity的新手。我有3个这样的课程

ClassA(ClassB b)
ClassB(ClassC c)
public class ClassC
{
    public string Name { get; set; }
}

当运行时我有classC.Name = "foo"时,我的问题是如何使用<ClassA>解析classC?我应该首先使用ClassB创建解决ClassC的工厂方法,然后使用ClassA解决ClassB吗?

有更好的方法吗?

1 个答案:

答案 0 :(得分:2)

根据我的理解,你有一些课程,比如ClientClass,需要在给定ClassA的实例的情况下创建ClassC的实例。

例如:

public class ClientClass
{
    public void SomeMethod()
    {
        ClassC class_c = ...
        ClassA class_a = CreateClassA(class_c);
    }
}

所以这意味着ClientClass需要一个看起来像这样的依赖:

public interface IClassAFactory
{
    ClassA Create(ClassC class_c);
}

此依赖项称为工厂,它允许您创建其他依赖项。

现在,在您决定需要工厂之前,看看您是否能够满足您的要求。看看this article

如果您决定需要工厂,请在需要它的同一装配中定义上述接口(ClientClass所在的位置)。

然后你需要创建一个使用容器创建ClassA对象的工厂实现。

以下是这样的工厂的样子:

public class UnityBasedClassAFactory : IClassAFactory
{
    private readonly IUnityContainer m_Container;

    public UnityBasedClassAFactory(IUnityContainer container)
    {
        m_Container = container;
    }

    public ClassA Create(ClassC class_c)
    {
        return m_Container.Resolve<ClassA>(new DependencyOverride<ClassC>(class_c));
    }
}

请注意,此工厂类需要存在于Composition Root中。如果您在其他任何地方创建它,则表示您使用的是Service Locator anti-pattern

现在,您需要将工厂界面注入ClientClass,如下所示:

public class ClientClass
{
    private readonly IClassAFactory m_ClassAFactory;

    public ClientClass(IClassAFactory class_a_factory)
    {
        m_ClassAFactory = class_a_factory;
    }

    public void SomeMethod()
    {
        ClassC class_c = ...; //runtime value
        ClassA class_a = m_ClassAFactory.Create(class_c);
    }
}

现在,您需要做的就是在您的Composition Root中注册工厂,如下所示:

container.RegisterType<IClassAFactory, UnityBasedClassAFactory>();