c# - Unity Container 同一接口(interface)的多种实现

标签 c# .net unity-container

我正在研究 unity 容器,有一个关于如何将类的构造解析为接口(interface)的多个不同实现的快速问题。

这是我的代码:

public interface IRenderer
{
    void DrawSquare(Square square);
    void DrawCircle(Circle circle);
}

public interface IShape
{
    void Draw(IRenderer renderer);
}

public class Dx11Renderer : IRenderer
{
    public void DrawSquare(Square square)
    {
    }

    public void DrawCircle(Circle circle)
    {
    }
}

public class GlRenderer : IRenderer
{
    public void DrawSquare(Square square)
    {
    }

    public void DrawCircle(Circle circle)
    {
    }
}

public class Circle : IShape
{
    public void Draw(IRenderer renderer) { renderer.DrawCircle(this); }   
}

public class Square
{
    public void Draw(IRenderer renderer) { renderer.DrawSquare(this); }   
}

public class Canvas
{
    private readonly IRenderer _renderer;

    private List<Circle> _circles = new List<Circle>();
    private List<Square> _squares = new List<Square>(); 

    public Canvas(IRenderer renderer)
    {
        _renderer = renderer;
    }

    public void Draw()
    {
        foreach (Circle c in _circles)
        {
            c.Draw(_renderer);
        }

        foreach (Square s in _squares)
        {
            s.Draw(_renderer);
        }
    }
}

并注册/解决

        // Create the container
        var container = new UnityContainer();

        // registration

        container.RegisterType<IRenderer, GlRenderer>("GL");
        container.RegisterType<IRenderer, Dx11Renderer>("DX11");

        Canvas canvas = container.Resolve<Canvas>("GL");

这会抛出一个“ResolutionFailedException”,所以我一定是用错了。

有人可以解释一下这是否是不好的做法,或者我如何才能做到这一点。

谢谢

更新:

所以我所做的是为每种类型的依赖项注册 Canvas 两次,如下所示:

// Canvas with an OpenGL Renderer
container.RegisterType<Canvas>("GLCanvas", new InjectionConstructor(new ResolvedParameter<IRenderer>("GL")));
// Canvas with a DirectX Renderer
container.RegisterType<Canvas>("DXCanvas", new InjectionConstructor(new ResolvedParameter<IRenderer>("DX11")));

Canvas canvas = container.Resolve<Canvas>("GLCanvas");

这很适合我!

最佳答案

问题是您正在使用名称“GL”解析 Canvas,但您没有以这种方式注册 Canvas。 Unity 不会将名称传播到依赖项解析,因此在解析 IRenderer 时不会使用名称“GL”。

有几个选项可以解决这个问题:Resolving named dependencies with Unity

你的问题是这是否是一种不好的做法,或者你如何才能达到同样的结果。根据我的经验,尝试注册和解析同一接口(interface)的多个实例通常会导致代码困惑。一种替代方法是使用工厂模式来创建 Canvas 的实例。

你需要用你的容器来解析Canvas吗?如果你没有理由不这样做,你可以简单地解析你的 IRenderer 并自己新建一个 Canvas :

new Canvas(container.Resolve<IRenderer>("GL"));

请记住,Unity 只是一种工具,如果它似乎无法满足您的需求,您可能需要另一种工具。

关于c# - Unity Container 同一接口(interface)的多种实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23669502/

相关文章:

c# - LINQ OrderByDescending 到 OrderByAscending?

c# - 如何在 Jetbrains Rider 中自动重新排列代码?

c# - 最小起订量错误 : Cannot cast 'AnObject' to 'System.Delegate'

c# - 具有不同名称的重复时区

c# - 使用Unity调用静态注入(inject)方法

c# - 如何在没有 Visual Studio 的情况下构建可移植类库?

c# - ASP.NET MVC : Razor <tr> do not match close tag

c# - 为什么未签名的 CLR 类型很难在 C# 中使用?

c# - 在 WPF 中使用 Unity

C# IUnityContainer 解析方法