最近研究了Ioc,DI 以及一些开源的框架,以下根据自己的理解写一个简单的Ioc容器。我们在使用一个依赖注入容器时一般都是实现三步:
- 创建一个Ioc容器;
- 依赖关系注入,这里需要一种collection对象存储这种注入关系;
- 根据依赖注入获取对象的实例;
好了,接下来我们可以按照测试驱动开发的模式完成一个简易版本的注入容器:MinContainer
- 测试代码:
[TestMethod]
public void CanNewContainerAndResolveType()
{
//
// TODO: Add test logic here
//
IMinContainer container = new MinContainer();
container.RegisterType(typeof(IDal),typeof(OracleDal));
//var dal = container.Resolve(typeof(IDal));
var dal = container.Resolve<IDal>();
Assert.IsNotNull(container);
Assert.IsInstanceOfType(dal, typeof(OracleDal));
}
- 定义接口
创建容器时定义了一个接口类型的容器,在这个接口中需要包含抽象方法的定义,看这个接口
public interface IMinContainer:IDisposable
{
void RegisterType(Type TFrom, Type Tto);
object Resolve(Type t);
TType Resolve<TType>();
}
- 实现接口
接下来就是实现这个接口,
public class MinContainer:IMinContainer
{
private bool disposed;
private readonly Dictionary<Type, TypeKeys> _regkey =
new Dictionary<Type, TypeKeys>();
#region IMinContainer Members
public void RegisterType(Type TFrom, Type Tto)
{
TypeKeys tk = new TypeKeys() { minType = TFrom, minInstance = CreateInstance(Tto) };
if (!_regkey.ContainsKey(TFrom))
_regkey.Add(TFrom, tk);
}
public object Resolve(Type t)
{
if(_regkey.ContainsKey(t))
return GetInstance(_regkey[t]);
throw new Exception("Type not registered" + t);
}
public TType Resolve<TType>()
{
return (TType)Resolve(typeof(TType));
}...
这里需要一个字典类型的集合器来保持注册的对象
public class TypeKeys
{
public Type minType { get; set; }
public object minInstance { get; set; }//类型实例
}
CreateInstance方法是创建对象的实例
private object CreateInstance(Type t)
{
var ctor = t.GetConstructors().First();
var parameters = ctor.GetParameters().Select(p => Resolve(p.ParameterType)).ToArray();
return ctor.Invoke(parameters);
}
在Resolve方法中GetInstance方法实现如下,主要是从字典中获取实例。
private object GetInstance(TypeKeys typekey)
{
return typekey.minInstance ??
(typekey.minInstance = CreateInstance(typekey.minType));
}
- 测试
好了,至此简单的原理级别的代码完成,测试。
在控制台中进行测试:
- 小结:
以上代码只是很简陋的原理实现,需要完善泛型实现,生命周期管理等,不过也很简单,大家可以到codeplex站点下载Unit, Munq等实现框架代码。