2010-06-17 6 views
5

Я пытаюсь начать с некоторой простой инъекции зависимости, используя C#, и я столкнулся с проблемой, на которую я, похоже, не могу найти ответ.C# зависимость инъекции - как вам вводить зависимость без источника?

У меня есть класс, написанный другим отделом, для которого у меня нет источника в моем проекте. Я хотел ввести объект этого типа, хотя конструктор с использованием интерфейса, но, конечно, я не могу изменить реализацию внедренных объектов для реализации интерфейса для достижения полиморфизма при бросании объекта в тип интерфейса.

Каждый академический пример, который я когда-либо видел в этой технике, использует классы, которые объявлены в самом проекте. Как я буду вводить свою зависимость без источника, доступного в проекте?

Я надеюсь, что имеет смысл, спасибо.

ответ

0

Если вам не нужно что-то менять в классе, вам вряд ли нужен код. Допустим, у вас есть класс X в DLL, который вы хотите вставить в другой класс Y, который вы пишете. В таком случае вы можете создать экземпляр X и поместить в качестве параметра в конструктор Y. Это будет выглядеть примерно так:

Добавьте ссылку на DLL, содержащий класс X в вашем проекте.

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. 
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.

+0

Это было именно то, о чем я думал. – Steven

+0

Адаптер шаблон. Хороший звонок. – Wix

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(); 
    } 
} 
+0

Но с последним из двух вариантов можно будет выполнить модульный тест собственного класса, который использует сторонний класс в качестве аргумента, переданного конструктору. то можно было бы издеваться над их классом с помощью ITheirClass –

+0

Оба варианта позволяют вам заменить свой класс (в общем случае, дженерики), но мой подход будет моим подходом. –

+0

Извините, я не имел в виду варианты 1 и 2. Обращался к цитате «.. всегда зависаю ...». Возможно, я неправильно понял. Возможно, вы имели в виду, что это не должно быть сделано только ради того, чтобы быть сделанным. Но хорошая практика означает, что мы сглаживаем путь для будущих изменений или технического обслуживания. Если класс был инъецирован, это облегчило бы его вводить, например, при измерении производительности? –

Смежные вопросы