Я пытаюсь начать с некоторым простым внедрением зависимости с помощью C#, и я столкнулся с проблемой, для которой я, может казаться, не придумываю ответ.
У меня есть класс, который был записан другим отделом, для которого у меня нет источника в моем проекте. Я хотел ввести объект этого типа, хотя конструктор, использующий интерфейс, но конечно, я не могу изменить введенную реализацию объектов для реализации интерфейса для достижения полиморфизма при кастинге объекта к интерфейсному типу.
Каждый академический пример, который я когда-либо видел этой техники, имеет классы использования классов, которые объявляются в самом проекте. Как я пошел бы о введении моей зависимости без источника, являющегося доступным в проекте?
Я надеюсь, что это имеет смысл, спасибо.
Вы можете создать обертку вокруг вашего целевого типа, например, у вас может быть класс, который они предоставляют:
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-контейнеров.
Если у вас нет необходимости менять что-либо в классе, вам вряд ли понадобится этот код. Предположим, у вас есть класс 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.
Вопрос в том, почему вы хотите внедрить его как интерфейс? Это потому, что класс реализует некоторые свойства / методы, которые вы хотели бы абстрагироваться, чтобы его можно было заменить, или вы просто пытаетесь «навязать» ему интерфейс маркера, потому что «мы всегда зависим от интерфейсов, а не от конкретных классов» ? Если последнее, то вы на неправильном пути, так как в любом случае, скорее всего, сразу бросили бы его на бетон.
Предполагая, что первое из двух, я вижу два варианта:
Для варианта 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();
}
}