自定义 IOC 容器 - 需要 2/3 类型的帮助
背景
为了帮助提高我对 IOC 及其使用方法的理解,我想创建一个包含所有三种 IOC 技术的示例:构造函数注入、Setter 注入和接口注入,而无需使用第三方框架。我想我有一个构造函数注入的基本示例,但在设置器和接口注入方面遇到了困难。
我的问题
您将如何从头开始解决编写接口和设置器注入问题?
这是我的想法,请告诉我我是否走在正确的道路上。
接口注入:
- 循环使用构造函数注入实例化的已解析对象,检查接口依赖映射中实现了哪些接口。
- 定义某种接口依赖映射以将接口与实现相关联。
- 使用 interfaceDependencyMap 解析实现
- 将适当的属性分配给使用构造函数注入初始化的对象
Setter 注入:
- 循环遍历使用构造函数注入实例化的已解析对象
- 定义某种 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));
}
}
Background
To help improve my understanding of IOC and how to use it, I want to create an example of all three IOC techniques: Constructor injection, Setter injection, and Interface injection without having to use a third party framework. I think I have a basic example of constructor injection, but struggling with setter and interface injection.
My Question
How would you approach tackling writing interface and setter injection from the ground up?
Here's my thoughts, let me know if I'm on the right track.
Interface injection:
- Loop through resolved objects instantiated using constructor injection,check to see what interfaces are implemented in interfaceDependencyMap
- Define some sort of interfaceDependencyMap to associate an interface to the implementation.
- Resolve the implementation using interfaceDependencyMap
- Assign the appropriate property to the object initialized with constructor injection
Setter injection:
- Loop through resolved objects instantiated using constructor injection
- Define some sort of setterInjectionMap
- Resolve the expected parameter from MethodInfo using the constructor mappings
- Call the setter method passing in the resolved parameter object
Here's what I have so far for constructor injection
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));
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这是您正在寻找的吗?
用法:
如果您想获得更高级的知识,我建议您获取其中任何一个的源代码:SimpleInjector,< a href="http://code.google.com/p/autofac/" rel="nofollow">Autofac, 注射, StructureMap。
Is this kind of what you're looking for?
Usage:
If you want to get more advanced, I would recommend getting the source of any of these: SimpleInjector, Autofac, Ninject, StructureMap.