Справочная информация
Чтобы помочь мне лучше понять IOC и то, как его использовать, я хочу создать пример всех трех методов IOC: инъекция в конструктор, инъекция в сеттер и инъекция в интерфейс без необходимости использования третьейпартийные рамки.Я думаю, что у меня есть базовый пример внедрения конструктора, но я борюсь с сеттером и внедрением интерфейса.
Мой вопрос
Как бы вы подошли к решению написания интерфейса и внедрения сеттера с нуля?
Вот мои мысли, дайте мне знать, если я на правильном пути.
Внедрение интерфейса:
- Цикл по разрешенным объектам, созданным с помощью внедрения в конструктор, проверьте, какие интерфейсы реализованы в interfaceDependencyMap
- Определите некоторый интерфейс interfaceDependencyMap для привязкиинтерфейс к реализации.
- Разрешите реализацию, используя interfaceDependencyMap
- Назначьте соответствующее свойство объекту, инициализированному с помощью инжектора конструктора
Внедрение сеттера:
- Цикл по разрешенным объектам, созданным с использованием инжектора конструктора
- Определение некоторого вида setterInjectionMap
- Разрешение ожидаемого параметра из MethodInfo с использованием отображений конструктора
- Вызов передачи метода setterв разрешенном объекте параметра
Вот что у меня есть для инжектора конструктора
public class Program
{
static void Main(string[] args)
{
//
//instead of doing this:
//
//ICreditCard creditCard = new Visa();
//var customer = new Customer(creditCard);
//customer.Charge();
var resolver = new Resolver();
//map the types in the container
resolver.Register<Customer, Customer>();
resolver.Register<ICreditCard, Visa>();
//because the customer constructor has an ICreditCard parameter
//our container will automatically instantiate it recursively
var customer = resolver.Resolve<Customer>();
customer.Charge();
}
}
public interface ICreditCard
{
string Charge();
}
public class Visa : ICreditCard
{
public string Charge()
{
return "Charging Visa";
}
}
public class MasterCard : ICreditCard
{
public string Charge()
{
return "Charging MasterCard";
}
}
public class Customer
{
private readonly ICreditCard _creditCard;
public Customer(ICreditCard creditCard)
{
this._creditCard = creditCard;
}
public void Charge()
{
_creditCard.Charge();
}
}
public class Resolver
{
private Dictionary<Type, Type> dependencyMap = new Dictionary<Type, Type>();
public T Resolve<T>()
{
return (T) Resolve(typeof (T));
}
private object Resolve(Type typeToResolve)
{
Type resolvedType = null;
try
{
resolvedType = dependencyMap[typeToResolve];
}
catch
{
throw new Exception(string.Format("could not resolve type {0}", typeToResolve.FullName));
}
var firstConstructor = resolvedType.GetConstructors().First();
var constructorParameters = firstConstructor.GetParameters();
if (constructorParameters.Count() == 0)
return Activator.CreateInstance(resolvedType);
IList<object> parameters = constructorParameters.Select(parameterToResolve => Resolve(parameterToResolve.ParameterType)).ToList();
return firstConstructor.Invoke(parameters.ToArray());
}
public void Register<TFrom, TTo>()
{
dependencyMap.Add(typeof (TFrom), typeof (TTo));
}
}