※This article is based on .NET 7
控制反转 (Inversion of Control) ,简称IoC,是面向对象编程中的一种设计原则,可以用来降低计算机代码之间的耦合度。通过控制反转,对象在被创建的时候,由一个调控系统内所有对象的外界实体将其所依赖的对象的引用传递给它。
在传统的程序开发中,开发人员往往会手动去new一个对象,换言之:对象的创建过程由开发人员控制。而在控制反转的原则下,系统中会存在一个专门的IoC容器,由IoC容器负责对象的创建。因此,创建对象的主动权从开发人员手中被移交到了容器手中,由容器控制对象的创建过程,这就是控制反转的含义。
下面就来编写一个简单的IoC容器,主要分为IoC、Controller、Service、Repository、Model五部分。依赖关系很简单,Controller—>Service—>Repository,最后在IoC中注册并调用,代码如下。
namespace App.Model
{
public class UserInfo
{
public string UserName { get; set; }
public string Password { get; set; }
}
}
using System.Collections.Generic;
using App.Model;
namespace App.Repository
{
public interface IUserInfoRepository
{
IEnumerable<UserInfo> GetUserInfoList();
}
}
using System.Collections.Generic;
using App.Model;
namespace App.Repository
{
public class UserInfoRepository : IUserInfoRepository
{
public IEnumerable<UserInfo> GetUserInfoList()
{
List<UserInfo> list = new List<UserInfo>();
list.Add(new UserInfo { UserName = "super", Password = "12345" });
list.Add(new UserInfo { UserName = "admin", Password = "12345" });
return list;
}
}
}
using System.Collections.Generic;
using App.Model;
namespace App.Service
{
public interface IUserInfoService
{
IEnumerable<UserInfo> GetUserInfoList();
}
}
using System;
using System.Collections.Generic;
using App.Model;
using App.Repository;
namespace App.Service
{
public class UserInfoService : IUserInfoService
{
private readonly IUserInfoRepository repository;
public UserInfoService(IUserInfoRepository repository)
{
this.repository = repository;
}
public IEnumerable<UserInfo> GetUserInfoList()
{
return repository.GetUserInfoList();
}
}
}
using System.Collections.Generic;
using App.Model;
namespace App.Controller
{
public interface IUserInfoController
{
IEnumerable<UserInfo> GetUserInfoList();
}
}
using System.Collections.Generic;
using App.Model;
using App.Service;
namespace App.Controller
{
public class UserInfoController : IUserInfoController
{
private readonly IUserInfoService service;
public UserInfoController(IUserInfoService service)
{
this.service = service;
}
public IEnumerable<UserInfo> GetUserInfoList()
{
return service.GetUserInfoList();
}
}
}
using System;
using System.Collections.Generic;
using System.Reflection;
namespace App.IoC
{
public class SimpleIocContainer
{
private readonly Dictionary<string, Type> container;
/// <summary>
/// 构造函数
/// </summary>
public SimpleIocContainer()
{
container = new Dictionary<string, Type>();
}
/// <summary>
/// 注册类型
/// </summary>
/// <typeparam name="TSuper">超类</typeparam>
/// <typeparam name="TSub">子类</typeparam>
public void RegisterType<TSuper, TSub>()
where TSuper : class
where TSub : class
{
string fullName = typeof(TSuper).FullName;
if (!container.ContainsKey(fullName))
{
container.Add(fullName, typeof(TSub));
}
}
/// <summary>
/// 获取需要的类型
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public T Resolve<T>() where T : class
{
string fullName = typeof(T).FullName;
if (!container.ContainsKey(fullName))
{
throw new Exception("Error");
}
return (T)CreateObject(container[fullName]);
}
/// <summary>
/// 递归创建对象
/// </summary>
/// <param name="type">子类类型</param>
/// <returns>object</returns>
private object CreateObject(Type type)
{
ConstructorInfo[] constructors = type.GetConstructors();
ConstructorInfo constructor = GetConstructor(constructors);
List<object> list = new List<object>();
foreach (ParameterInfo parameter in constructor.GetParameters())
{
Type paraType = parameter.ParameterType;
if (!container.ContainsKey(paraType.FullName))
{
throw new Exception("Error");
}
list.Add(CreateObject(container[paraType.FullName]));
}
return Activator.CreateInstance(type, list.ToArray());
}
/// <summary>
/// 获取构造函数
/// </summary>
/// <param name="constructors">构造函数集合</param>
/// <returns>构造函数</returns>
private ConstructorInfo GetConstructor(ConstructorInfo[] constructors)
{
// 构造函数个数为0,则抛出异常
if (constructors.Length == 0)
{
throw new Exception("Error");
}
// 构造函数个数为1,则直接返回
if (constructors.Length == 1)
{
return constructors[0];
}
// 获取形参个数最多的构造函数
ConstructorInfo constructor = constructors[0];
foreach (var item in constructors)
{
if (item.GetParameters().Length > constructor.GetParameters().Length)
{
constructor = item;
}
}
return constructor;
}
}
}
using System;
using App.Controller;
using App.IoC;
using App.Repository;
using App.Service;
namespace App
{
class Program
{
static void Main(string[] args)
{
// 创建IoC容器,注册接口和类
var container = new SimpleIocContainer();
container.RegisterType<IUserInfoRepository, UserInfoRepository>();
container.RegisterType<IUserInfoService, UserInfoService>();
container.RegisterType<IUserInfoController, UserInfoController>();
// 利用IoC容器自动创建对象
var controller = container.Resolve<IUserInfoController>();
// 输出结果
var list = controller.GetUserInfoList();
foreach (var item in list)
{
Console.WriteLine(item.UserName + "," + item.Password);
}
Console.ReadKey(true);
}
}
}
运行结果如下所示:
super,12345 admin,12345
在上面的代码中,我们并没有手动去创建Repository、Service、Controller这些类的实例,而是通过在IoC容器中注册它们的依赖关系,然后通过Resolve方法自动创建对应的实例。这也就是上面所说的:把创建对象的主动权交给容器,让容器帮助我们自动创建对象。上面给出的只是一个最简单的IoC容器实现方法,有兴趣的同志可以参考Autofac、Unity等第三方框架进行拓展。
コメント: