手写简单的IOC容器
·
Prism 本身并不强制使用特定的 IoC 容器(它支持 Unity、DryIoc、Autofac、Microsoft.Extensions.DependencyInjection 等),但其核心思想是通过容器管理对象生命周期、自动解析依赖。
下面逐步设计并实现一个简化版的 IoC 容器,具备以下功能:
- 注册类型(支持瞬态、单例)
- 解析服务(支持构造函数注入)
- 自动解析依赖链
- 基础生命周期管理
🧱 第一步:明确核心概念
1. 服务注册表(Service Registry)
存储“服务类型 → 实现类型/工厂”的映射。
2. 生命周期管理
Transient:每次解析都创建新实例Singleton:整个容器中只创建一次,后续返回同一实例
3. 依赖解析器(Resolver)
根据类型,递归解析其构造函数参数所需的依赖。
🛠 第二步:定义接口和枚举
public enum Lifetime
{
Transient,
Singleton
}
public interface IContainer
{
void Register<TService, TImplementation>(Lifetime lifetime = Lifetime.Transient)
where TImplementation : class, TService
where TService : class;
void Register<TService>(Lifetime lifetime = Lifetime.Transient)
where TService : class;
T Resolve<T>() where T : class;
object Resolve(Type serviceType);
}
📦 第三步:实现注册项(Registration)
public class ServiceRegistration
{
public Type ServiceType { get; }
public Type ImplementationType { get; }
public Lifetime Lifetime { get; }
public ServiceRegistration(Type serviceType, Type implementationType, Lifetime lifetime)
{
ServiceType = serviceType;
ImplementationType = implementationType;
Lifetime = lifetime;
}
}
🧠 第四步:实现容器核心逻辑
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
public class SimpleContainer : IContainer
{
private readonly Dictionary<Type, ServiceRegistration> _registrations = new();
private readonly Dictionary<Type, object> _singletonInstances = new();
public void Register<TService, TImplementation>(Lifetime lifetime = Lifetime.Transient)
where TImplementation : class, TService
where TService : class
{
var registration = new ServiceRegistration(typeof(TService), typeof(TImplementation), lifetime);
_registrations[typeof(TService)] = registration;
}
public void Register<TService>(Lifetime lifetime = Lifetime.Transient)
where TService : class
{
// 自绑定:服务即实现
Register<TService, TService>(lifetime);
}
public T Resolve<T>() where T : class => (T)Resolve(typeof(T));
public object Resolve(Type serviceType)
{
if (!_registrations.TryGetValue(serviceType, out var registration))
throw new InvalidOperationException($"Service {serviceType} is not registered.");
if (registration.Lifetime == Lifetime.Singleton)
{
if (_singletonInstances.TryGetValue(serviceType, out var existing))
return existing;
var instance = CreateInstance(registration.ImplementationType);
_singletonInstances[serviceType] = instance;
return instance;
}
return CreateInstance(registration.ImplementationType);
}
private object CreateInstance(Type type)
{
// 获取最匹配的公共构造函数(这里简化:选参数最多的)
var constructors = type.GetConstructors(BindingFlags.Public | BindingFlags.Instance);
if (constructors.Length == 0)
throw new InvalidOperationException($"No public constructor found for {type}.");
var constructor = constructors.OrderByDescending(c => c.GetParameters().Length).First();
var parameters = constructor.GetParameters()
.Select(p => Resolve(p.ParameterType))
.ToArray();
return constructor.Invoke(parameters);
}
}
✅ 第五步:测试用例
// 示例服务
public interface ILogger
{
void Log(string message);
}
public class ConsoleLogger : ILogger
{
public void Log(string message) => Console.WriteLine($"LOG: {message}");
}
public class EmailService
{
private readonly ILogger _logger;
public EmailService(ILogger logger)
{
_logger = logger;
}
public void Send(string to, string msg)
{
_logger.Log($"Sending email to {to}: {msg}");
}
}
// 使用容器
class Program
{
static void Main()
{
var container = new SimpleContainer();
container.Register<ILogger, ConsoleLogger>(Lifetime.Singleton);
container.Register<EmailService>(Lifetime.Transient);
var email1 = container.Resolve<EmailService>();
var email2 = container.Resolve<EmailService>();
email1.Send("alice@example.com", "Hello");
email2.Send("bob@example.com", "Hi");
// 验证是否是同一个 logger(单例)
var logger1 = container.Resolve<ILogger>();
var logger2 = container.Resolve<ILogger>();
Console.WriteLine(ReferenceEquals(logger1, logger2)); // True
}
}
🔧 第六步:可扩展方向(进阶)
你的简易容器已经能工作了!接下来可以考虑增强:
| 功能 | 实现思路 |
|---|---|
| 工厂注册 | 支持 Register<T>(factory: () => new T()) |
| 命名注册 | 支持多个同类型不同实现(如 Register<ILogger>("file")) |
| 属性注入 | 在 CreateInstance 后反射设置属性 |
| 泛型支持 | 处理 IRepository<T> → Repository<T> |
| 作用域生命周期(Scoped) | 引入 CreateScope() 方法 |
| 自动批量注册 | 扫描程序集,按约定注册 |
📌 总结:实现步骤回顾
- 定义接口:
IContainer+ 生命周期枚举 - 设计注册模型:
ServiceRegistration - 实现注册方法:支持泛型、自绑定
- 实现解析逻辑:递归解析构造函数依赖
- 管理单例缓存
- 测试验证
- 逐步扩展
💡 虽然这个容器很基础,但它体现了 IoC 的核心思想:解耦对象创建与使用,由容器负责依赖组装。
更多推荐
所有评论(0)