C#依赖注入 - 如何在没有源代码的情况下注入依赖项?

6

我正在尝试使用C#进行简单的依赖注入,并遇到了一个问题,我似乎找不到答案。

我有一个类,是由另一个部门编写的,但我在我的项目中没有源代码。我想通过构造函数使用接口注入这种类型的对象,但是当将对象转换为接口类型时,我无法更改注入对象的实现以实现多态。

我曾见过的每个学术示例都使用在项目本身中声明的类。如果没有可用于项目的源代码,我该如何注入依赖项?

希望这样说有意义,谢谢。

3个回答

6
你可以创建一个目标类型的包装器,例如,你可以提供一个类:
public class TheirClass
{
  public void DoSomething();
}

使用此功能可以定义一个接口:

public interface ITheirClass
{
  void DoSomething();
}

在一个包装类上实现该接口:

public class TheirClassWrapper : TheirClass, ITheirClass
{

}

或者,如果他们提供的类是密封的,则需要稍微不同的方法:

public class TheirClassWrapper : ITheirClass
{
  private TheirClass instance = new TheirClass();

  public void DoSomething()
  {
    instance.DoSomething();
  }
}

那么您可以注入该接口。

我知道在MEF中,我们可以导出具体类型并正确地注入它们,但我不确定其他IoC容器是否也能做到。


这正是我所想的。 - Steven

1
问题是,为什么要将它作为接口注入?是因为该类实现了一些属性/方法,您想要将其抽象出来以便进行替换,还是只是试图将标记接口“强制”添加到其中,因为“我们总是依赖于接口,而不是具体类”?如果是后者,那么您走错了路,因为您很可能会立即将其转换为具体类。

假设以上两种情况中的前者,我可以看到两个选项:

  1. 改用继承。这取决于类的创建方式,可能可行,但您可以从中继承并用新类替换旧类。
  2. 自己创建接口,使用您需要的方法/属性,并在实现接口的类中包装外部具体类。

对于选项2,如果您无法继承,例如,假设您只关心类中的一个方法(我们称之为Method1()),则可以为其创建匹配的接口:

public interface IMyNewInterface
{
    void Method1();
}

然后创建一个实现它的类,将具体的类作为依赖项(像正常情况下由容器注入)并调用具体的类:

public class MyNewClass : IMyNewInterface
{
    private MyConcreteClass _MyConcreteClass;

    public void MyNewClass(MyConcreteClass concreteClass)
    {
        _MyConcreteClass = concreteClass;
    }

    public void Method1()
    {
        _MyConcreteClass.Method1();
    }
}

但是使用后一种选项,您可以对使用第三方类作为构造函数传递的参数的自己的类进行单元测试。也就是说,您可以使用ITheirClass模拟TheirClass。 - Dave Archer
两种选项都可以替换它们的类(泛型除外),但我更喜欢接口方法。 - Steven Robbins
抱歉,我不是指选项1和2。我是在提到“..我们总是依赖于...”这句话。也许我看错了。也许你的意思是不能只为了完成而完成。但是好的实践意味着我们为未来的更改或维护铺平道路。如果该类被注入,那么将更容易使用例如aop性能测量进行注入? - Dave Archer
当然,依赖接口是一个好的实践方法,我只是想确保发帖者知道为什么我们这样做,而不仅仅是因为某个地方有一个“我们总是使用接口”的评论。取决于外部类是/做什么,会决定我是否值得包装 - 像所有事情一样,你必须是务实的并运用你的头脑 :-) - Steven Robbins
那真是太棒了,谢谢你们的帮助。整个目标是允许单元测试,我一定会考虑是否值得注入类,而不是盲目地注入所有内容。感谢大家的帮助。 - Phil Harris

0

如果您不需要更改类中的任何内容,那么您几乎不需要代码。假设您有一个名为X的类位于DLL中,您希望将其注入到另一个您正在编写的Y类中。在这种情况下,您可以创建X的实例,并将其作为构造函数中Y的参数。示例如下:

将包含类X的DLL添加到您的项目中的引用中。

Use NameSpaceOfX;
Class Y
{
    Public Y() //Default constructor
    {
    }

    Public Y(X instanceOfX)
    {
        //Use instanceOfX here as required
    }
}

在你的主代码中:
//Create instance of X
X instanceOfX = new X();
//Inject it into Y
Y instanceOfY = new Y(instanceOfX);
//Use Y now.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接