一、为什么需要IOC容器
IOC容器在大学学习中应该会经常见到,比如Java中大名鼎鼎的Spring架构,还有C#中的Autofac。
IOC容器可以帮助我们解耦对象之间的依赖关系,让对象只需关注自己的业务逻辑,而不需要关心如何创建和维护其他对象。
我这么说可能太过于高大上,我们举一个浅显的例子
假设我们有一个餐厅管理系统,它由三个类组成:
1.餐厅类(Restaurant),
2.厨师类(Chef)
3.服务员类(Waiter)。
餐厅类需要一个厨师类和一个服务员类来运行,也就是说餐厅类依赖于这两个类,有时可能需要更换。我们可以使用IOC容器来管理这些依赖关系。
二、IOC容器达到的效果
我们首先还原上文的情景,实现这些类,其中最难处理的便是餐厅类了,对厨师和服务员都有依赖,我们首先实现独立的两个类
public interface IChef{
void Cook();}
public interface IWaiter{
void Serve();}
class Chef : IChef
{
public void Cook() {
/* code to cook the food */ }
}
class Waiter : IWaiter
{
public void Serve() {
/* code to serve the food */ }
}
接下来处理餐厅类,因为餐厅类依赖于服务员,依赖于厨师,但是难免要更换厨师和服务员。
我们不用关注IOC容器的实现方式,只需要看这张图
需要厨师时我们拿到IChef接口,不关心具体实现的类型
需要服务员拿IWaiter接口,不关心实现类型
也就是说,我们餐厅对于服务员和厨师,只关心他们能否做饭(IChef)和服务(IWaiter),而不是他们其他的内容。
而IOCContainer就是负责绑定具体和抽象的一个媒介。这里不要纠结IOCContainer的实现,后文将给出具体实现。
class Restaurant
{
//这里定义一个容器,存储依赖关系
private IOContainer _container;
public Restaurant(IOContainer container)
{
_container = container;
//把接口和类型绑定依赖关系
_container.Register<IChef, Chef>();
_container.Register<IWaiter, Waiter>();
}
public void Serve()
{
//解析依赖关系
var chef = _container.Reslove<IChef>();
var waiter = _container.Reslove<IWaiter>();
chef.Cook();
waiter.Serve();
}
}
class Program
{
static void Main(string[] args)
{
//建立IOC容器
var container = new IOContainer();
//餐厅对象
var restaurant = new Restaurant(container);
//调用方法
restaurant.Serve();
}
}
三、简易IOC容器实现
正如你所见,IOC容器唯一的作用就是绑定抽象和具体,实现控制反转,不需要多么花里胡哨,大道至简。
在代码中,笔者将给出详细的注释。
public class IOContainer
{
//首先实现依赖关系存储,Key为接口类型,object为实例
private Dictionary<Type, object> container = new Dictionary<Type, object>();
public void Register<T,K>() where K : class, T
{
Register<T>(Activator.CreateInstance<K>());
}
//绑定依赖
public void Register<T>(T instance)
{
Type key = typeof(T);
if (container.ContainsKey(key))
{
container[key] = instance;
}
else
{
container.Add(key, instance);
}
}
//解析依赖
public T Reslove<T>() where T : class
{
if (container.ContainsKey(typeof(T)))
{
return container[typeof(T)] as T;
}
throw new NullReferenceException("No such type in this IOCContainer!");
}
}
如果对你有帮助,可以点一个免费的赞或者关注笔者,在Github上为yueh0607的项目点一个star(三克油)