moklgy's blog moklgy's blog
首页
  • 前端文章

    • JavaScript
  • 学习笔记

    • 《JavaScript教程》
    • 《JavaScript高级程序设计》
    • 《ES6 教程》
    • 《Vue》
    • 《React》
    • 《TypeScript 从零实现 axios》
    • 《Git》
    • TypeScript
    • JS设计模式总结
  • 后端文章

    • 技术题
  • .netcore

    • 《asp.netcore》笔记
    • 《设计模式》
  • HTML
  • CSS
  • 技术文档
  • GitHub技巧
  • Nodejs
  • 博客搭建
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

moklgy docs

全栈初级开发工程师
首页
  • 前端文章

    • JavaScript
  • 学习笔记

    • 《JavaScript教程》
    • 《JavaScript高级程序设计》
    • 《ES6 教程》
    • 《Vue》
    • 《React》
    • 《TypeScript 从零实现 axios》
    • 《Git》
    • TypeScript
    • JS设计模式总结
  • 后端文章

    • 技术题
  • .netcore

    • 《asp.netcore》笔记
    • 《设计模式》
  • HTML
  • CSS
  • 技术文档
  • GitHub技巧
  • Nodejs
  • 博客搭建
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 依赖注入
    • 第一步:理解依赖注入的核心概念
      • 什么是依赖注入?
      • 为什么需要依赖注入容器?
    • 第二步:定义核心接口和类型
      • 原理解释:
    • 第三步:实现ServiceDescriptor
      • 为什么这样设计:
    • 第四步:实现服务集合
      • 为什么这样设计:
    • 第五步:实现作用域接口
      • 作用域的作用:
    • 第六步:实现依赖注入容器
      • 容器设计说明:
    • 第七步:完善扩展方法
    • 第八步:使用依赖注入容器
    • 高级特性解释
      • 1. 构造函数注入
      • 2. 属性注入
      • 3. 生命周期管理
      • 4. 服务集合注入
    • 总结
  • 中间件基础
  • 中间件高级
  • netcore》笔记
moklgydocs
2025-10-12
目录

依赖注入

# 从零开发一个中等难度的依赖注入容器

作为.NET Core专家,我将带您一步一步开发一个功能完善的依赖注入容器。在这个过程中,我会详细讲解每一步的原理、目的以及具体实现。

# 第一步:理解依赖注入的核心概念

# 什么是依赖注入?

依赖注入(Dependency Injection,简称DI)是一种设计模式,它允许我们将对象的创建与使用分离。通过DI,类不再负责创建它所依赖的对象,而是从外部接收这些依赖。

// 不使用DI:强耦合
public class UserService {
    private readonly DatabaseRepository _repository = new DatabaseRepository();
    
    public void SaveUser(User user) {
        _repository.Save(user);
    }
}

// 使用DI:解耦
public class UserService {
    private readonly IRepository _repository;
    
    // 依赖从外部注入
    public UserService(IRepository repository) {
        _repository = repository;
    }
    
    public void SaveUser(User user) {
        _repository.Save(user);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

# 为什么需要依赖注入容器?

  1. 管理对象生命周期:控制对象何时创建、如何复用
  2. 自动解析依赖关系:自动创建复杂对象图
  3. 简化配置:集中管理服务注册
  4. 促进松耦合:依赖于抽象而非具体实现
  5. 便于测试:轻松替换真实实现为模拟对象

# 第二步:定义核心接口和类型

首先,我们需要定义几个基础接口和类型:

using System;
using System.Collections.Generic;

namespace CustomDI
{
    // 定义服务生命周期
    public enum ServiceLifetime
    {
        Singleton,   // 单例:整个应用程序生命周期内只创建一次
        Scoped,      // 作用域:在同一个作用域内只创建一次
        Transient    // 临时:每次请求都创建新实例
    }
    
    // 服务描述:包含服务类型、实现和生命周期信息
    public class ServiceDescriptor
    {
        public Type ServiceType { get; }
        public Type ImplementationType { get; }
        public object Instance { get; internal set; }
        public Func<IServiceProvider, object> Factory { get; }
        public ServiceLifetime Lifetime { get; }
        
        // 构造函数和工厂方法将在后面实现
    }
    
    // 服务集合:用于注册服务
    public interface IServiceCollection : IList<ServiceDescriptor>
    {
    }
    
    // 服务提供者:用于解析服务
    public interface IServiceProvider
    {
        object GetService(Type serviceType);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

# 原理解释:

  • ServiceLifetime:定义服务的生命周期,影响实例的创建和缓存策略
  • ServiceDescriptor:描述一个服务注册,包含服务类型、如何创建服务及其生命周期
  • IServiceCollection:服务注册的容器,用于配置阶段
  • IServiceProvider:服务解析的入口,用于运行时获取服务实例

# 第三步:实现ServiceDescriptor

ServiceDescriptor是依赖注入系统的核心数据结构,它包含了如何创建和管理服务实例的所有信息:

public class ServiceDescriptor
{
    public Type ServiceType { get; }
    public Type ImplementationType { get; }
    public object Instance { get; internal set; }
    public Func<IServiceProvider, object> Factory { get; }
    public ServiceLifetime Lifetime { get; }

    // 基于实现类型的描述符
    private ServiceDescriptor(Type serviceType, Type implementationType, ServiceLifetime lifetime)
    {
        ServiceType = serviceType;
        ImplementationType = implementationType;
        Lifetime = lifetime;
    }

    // 基于实例的描述符
    private ServiceDescriptor(Type serviceType, object instance)
    {
        ServiceType = serviceType;
        Instance = instance;
        Lifetime = ServiceLifetime.Singleton; // 实例总是单例
    }

    // 基于工厂的描述符
    private ServiceDescriptor(Type serviceType, Func<IServiceProvider, object> factory, ServiceLifetime lifetime)
    {
        ServiceType = serviceType;
        Factory = factory;
        Lifetime = lifetime;
    }

    // 工厂方法:创建基于类型的描述符
    public static ServiceDescriptor Describe(Type serviceType, Type implementationType, ServiceLifetime lifetime)
        => new ServiceDescriptor(serviceType, implementationType, lifetime);

    // 以下是便捷的创建方法
    public static ServiceDescriptor Singleton(Type serviceType, Type implementationType)
        => Describe(serviceType, implementationType, ServiceLifetime.Singleton);

    public static ServiceDescriptor Singleton<TService, TImplementation>()
        where TImplementation : TService
        => Singleton(typeof(TService), typeof(TImplementation));

    public static ServiceDescriptor Singleton(Type serviceType, object instance)
        => new ServiceDescriptor(serviceType, instance);

    public static ServiceDescriptor Singleton<TService>(object instance)
        => Singleton(typeof(TService), instance);

    public static ServiceDescriptor Singleton<TService>(Func<IServiceProvider, object> factory)
        => new ServiceDescriptor(typeof(TService), factory, ServiceLifetime.Singleton);

    public static ServiceDescriptor Scoped(Type serviceType, Type implementationType)
        => Describe(serviceType, implementationType, ServiceLifetime.Scoped);

    public static ServiceDescriptor Scoped<TService, TImplementation>()
        where TImplementation : TService
        => Scoped(typeof(TService), typeof(TImplementation));

    public static ServiceDescriptor Scoped<TService>(Func<IServiceProvider, object> factory)
        => new ServiceDescriptor(typeof(TService), factory, ServiceLifetime.Scoped);

    public static ServiceDescriptor Transient(Type serviceType, Type implementationType)
        => Describe(serviceType, implementationType, ServiceLifetime.Transient);

    public static ServiceDescriptor Transient<TService, TImplementation>()
        where TImplementation : TService
        => Transient(typeof(TService), typeof(TImplementation));

    public static ServiceDescriptor Transient<TService>(Func<IServiceProvider, object> factory)
        => new ServiceDescriptor(typeof(TService), factory, ServiceLifetime.Transient);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73

# 为什么这样设计:

  1. 私有构造函数 + 公共工厂方法:这种模式可以提供更清晰的API,使用者只需要使用适当的工厂方法来创建描述符
  2. 三种注册方式:
    • 类型到类型的映射:最常见的注册方式,服务接口映射到具体实现类
    • 直接实例:提前创建的实例,总是作为单例
    • 工厂方法:允许自定义复杂的实例创建逻辑
  3. 泛型和非泛型API:提供两种API风格,增强灵活性和类型安全

# 第四步:实现服务集合

服务集合用于在应用程序启动时注册服务:

public class ServiceCollection : List<ServiceDescriptor>, IServiceCollection
{
    // 继承了List<ServiceDescriptor>的所有功能
}

// 扩展方法,提供流畅的API
public static class ServiceCollectionExtensions
{
    public static IServiceCollection AddSingleton<TService, TImplementation>(this IServiceCollection services)
        where TImplementation : TService
    {
        services.Add(ServiceDescriptor.Singleton<TService, TImplementation>());
        return services;
    }

    public static IServiceCollection AddSingleton<TService>(this IServiceCollection services, TService instance)
    {
        services.Add(ServiceDescriptor.Singleton(typeof(TService), instance));
        return services;
    }

    public static IServiceCollection AddSingleton<TService>(this IServiceCollection services, Func<IServiceProvider, TService> factory)
    {
        services.Add(ServiceDescriptor.Singleton<TService>(sp => factory(sp)));
        return services;
    }

    public static IServiceCollection AddScoped<TService, TImplementation>(this IServiceCollection services)
        where TImplementation : TService
    {
        services.Add(ServiceDescriptor.Scoped<TService, TImplementation>());
        return services;
    }

    public static IServiceCollection AddScoped<TService>(this IServiceCollection services, Func<IServiceProvider, TService> factory)
    {
        services.Add(ServiceDescriptor.Scoped<TService>(sp => factory(sp)));
        return services;
    }

    public static IServiceCollection AddTransient<TService, TImplementation>(this IServiceCollection services)
        where TImplementation : TService
    {
        services.Add(ServiceDescriptor.Transient<TService, TImplementation>());
        return services;
    }

    public static IServiceCollection AddTransient<TService>(this IServiceCollection services, Func<IServiceProvider, TService> factory)
    {
        services.Add(ServiceDescriptor.Transient<TService>(sp => factory(sp)));
        return services;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

# 为什么这样设计:

  1. 直接继承List:复用已有集合功能,避免重复造轮子
  2. 扩展方法:提供强类型、流畅的API,使服务注册代码更简洁可读
  3. 方法链式调用:返回服务集合自身,支持链式API风格
  4. 多种注册重载:支持不同的注册方式,提高灵活性

# 第五步:实现作用域接口

在实现容器前,我们需要定义作用域相关的接口:

// 服务作用域:管理作用域内服务的生命周期
public interface IServiceScope : IDisposable
{
    IServiceProvider ServiceProvider { get; }
}

// 服务作用域工厂:创建新的服务作用域
public interface IServiceScopeFactory
{
    IServiceScope CreateScope();
}
1
2
3
4
5
6
7
8
9
10
11

# 作用域的作用:

  1. 隔离请求:在Web应用中,每个HTTP请求需要独立的服务实例
  2. 资源管理:作用域结束时释放资源
  3. 状态隔离:不同作用域内的状态互不影响

# 第六步:实现依赖注入容器

现在,我们可以实现核心容器类了:

using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

namespace CustomDI
{
    public class DIContainer : IServiceProvider, IServiceScopeFactory, IDisposable
    {
        private readonly Dictionary<Type, List<ServiceDescriptor>> _serviceDescriptors;
        private readonly ConcurrentDictionary<ServiceCacheKey, object> _singletonInstances;
        private readonly ConcurrentDictionary<ServiceCacheKey, object> _scopedInstances;
        private readonly DIContainer _rootContainer;
        private bool _disposed;

        // 用于服务实例缓存的键
        private readonly struct ServiceCacheKey : IEquatable<ServiceCacheKey>
        {
            public readonly Type Type;
            public readonly int? ImplementationIndex;

            public ServiceCacheKey(Type type, int? implementationIndex = null)
            {
                Type = type;
                ImplementationIndex = implementationIndex;
            }

            public bool Equals(ServiceCacheKey other)
                => Type == other.Type && ImplementationIndex == other.ImplementationIndex;

            public override bool Equals(object obj)
                => obj is ServiceCacheKey key && Equals(key);

            public override int GetHashCode()
                => HashCode.Combine(Type, ImplementationIndex);
        }

        // 根容器构造函数,用于初始创建
        public DIContainer(IServiceCollection services)
        {
            _rootContainer = this;
            _serviceDescriptors = new Dictionary<Type, List<ServiceDescriptor>>();
            _singletonInstances = new ConcurrentDictionary<ServiceCacheKey, object>();
            _scopedInstances = new ConcurrentDictionary<ServiceCacheKey, object>();

            // 处理服务注册
            foreach (var descriptor in services)
            {
                if (!_serviceDescriptors.TryGetValue(descriptor.ServiceType, out var descriptors))
                {
                    descriptors = new List<ServiceDescriptor>();
                    _serviceDescriptors[descriptor.ServiceType] = descriptors;
                }
                descriptors.Add(descriptor);
            }

            // 注册容器自身
            RegisterContainerServices();
        }

        // 用于创建子作用域的构造函数
        private DIContainer(DIContainer rootContainer)
        {
            _rootContainer = rootContainer;
            _serviceDescriptors = rootContainer._serviceDescriptors;
            _singletonInstances = rootContainer._singletonInstances;
            _scopedInstances = new ConcurrentDictionary<ServiceCacheKey, object>();
        }

        // 注册容器自身提供的服务
        private void RegisterContainerServices()
        {
            // 注册自身为服务提供者
            if (!_serviceDescriptors.ContainsKey(typeof(IServiceProvider)))
            {
                _serviceDescriptors[typeof(IServiceProvider)] = new List<ServiceDescriptor>
                {
                    ServiceDescriptor.Singleton(typeof(IServiceProvider), this)
                };
            }

            // 注册作用域工厂
            if (!_serviceDescriptors.ContainsKey(typeof(IServiceScopeFactory)))
            {
                _serviceDescriptors[typeof(IServiceScopeFactory)] = new List<ServiceDescriptor>
                {
                    ServiceDescriptor.Singleton(typeof(IServiceScopeFactory), this)
                };
            }
        }

        // 实现IServiceProvider接口
        public object GetService(Type serviceType)
        {
            if (_disposed)
            {
                throw new ObjectDisposedException(nameof(DIContainer));
            }

            // 处理服务集合请求
            if (IsServiceCollection(serviceType, out var elementType))
            {
                return ResolveServices(elementType);
            }

            // 获取服务注册信息
            if (!_serviceDescriptors.TryGetValue(serviceType, out var descriptors) || descriptors.Count == 0)
            {
                return null; // 未注册的服务返回null
            }

            // 获取默认实现(最后注册的服务)
            var descriptor = descriptors.Last();
            return ResolveService(descriptor);
        }

        // 检查是否是集合类型
        private bool IsServiceCollection(Type serviceType, out Type elementType)
        {
            elementType = null;

            if (serviceType.IsGenericType)
            {
                var genericType = serviceType.GetGenericTypeDefinition();
                if (genericType == typeof(IEnumerable<>) || 
                    genericType == typeof(ICollection<>) || 
                    genericType == typeof(IList<>))
                {
                    elementType = serviceType.GetGenericArguments()[0];
                    return true;
                }
            }

            return false;
        }

        // 解析服务集合
        private object ResolveServices(Type elementType)
        {
            if (!_serviceDescriptors.TryGetValue(elementType, out var descriptors))
            {
                // 返回空集合
                var listType = typeof(List<>).MakeGenericType(elementType);
                return Activator.CreateInstance(listType);
            }

            var instances = new List<object>();
            for (int i = 0; i < descriptors.Count; i++)
            {
                var instance = ResolveService(descriptors[i], i);
                if (instance != null)
                {
                    instances.Add(instance);
                }
            }

            // 转换为请求的集合类型
            var array = Array.CreateInstance(elementType, instances.Count);
            for (int i = 0; i < instances.Count; i++)
            {
                array.SetValue(instances[i], i);
            }

            return array;
        }

        // 解析单个服务
        private object ResolveService(ServiceDescriptor descriptor, int? index = null)
        {
            var cacheKey = new ServiceCacheKey(descriptor.ServiceType, index);

            switch (descriptor.Lifetime)
            {
                case ServiceLifetime.Singleton:
                    return _rootContainer._singletonInstances.GetOrAdd(cacheKey, _ => CreateInstance(descriptor));
                
                case ServiceLifetime.Scoped:
                    return _scopedInstances.GetOrAdd(cacheKey, _ => CreateInstance(descriptor));
                
                case ServiceLifetime.Transient:
                    return CreateInstance(descriptor);
                
                default:
                    throw new NotSupportedException($"不支持的生命周期类型: {descriptor.Lifetime}");
            }
        }

        // 创建服务实例
        private object CreateInstance(ServiceDescriptor descriptor)
        {
            // 如果已有实例,直接返回
            if (descriptor.Instance != null)
            {
                return descriptor.Instance;
            }

            // 如果有工厂方法,使用工厂创建
            if (descriptor.Factory != null)
            {
                return descriptor.Factory(this);
            }

            // 通过类型创建实例
            return ActivateInstance(descriptor.ImplementationType);
        }

        // 激活类型实例
        private object ActivateInstance(Type type)
        {
            // 获取所有构造函数
            var constructors = type.GetConstructors();
            if (constructors.Length == 0)
            {
                // 没有公共构造函数,尝试使用默认构造函数
                return Activator.CreateInstance(type);
            }

            // 选择参数最多的构造函数(通常是主构造函数)
            var constructor = constructors
                .OrderByDescending(c => c.GetParameters().Length)
                .First();

            // 解析构造函数参数
            var parameters = constructor.GetParameters();
            var parameterInstances = new object[parameters.Length];

            for (int i = 0; i < parameters.Length; i++)
            {
                var parameter = parameters[i];
                parameterInstances[i] = GetService(parameter.ParameterType);
                
                // 如果参数不是可选的,但无法解析,抛出异常
                if (parameterInstances[i] == null && !parameter.IsOptional)
                {
                    throw new InvalidOperationException(
                        $"无法解析类型 {type.FullName} 的构造函数参数 {parameter.Name} (类型: {parameter.ParameterType.FullName})");
                }
            }

            // 创建实例
            var instance = constructor.Invoke(parameterInstances);

            // 属性注入
            InjectProperties(instance);

            return instance;
        }

        // 属性注入
        private void InjectProperties(object instance)
        {
            var type = instance.GetType();
            
            // 查找标记了 [Inject] 特性的属性
            foreach (var property in type.GetProperties(BindingFlags.Public | BindingFlags.Instance))
            {
                var injectAttribute = property.GetCustomAttribute<InjectAttribute>();
                if (injectAttribute != null)
                {
                    var propertyValue = GetService(property.PropertyType);
                    if (propertyValue != null)
                    {
                        property.SetValue(instance, propertyValue);
                    }
                }
            }
        }

        // 实现IServiceScopeFactory接口
        public IServiceScope CreateScope()
        {
            if (_disposed)
            {
                throw new ObjectDisposedException(nameof(DIContainer));
            }

            return new ServiceScope(new DIContainer(_rootContainer));
        }

        // 实现IDisposable接口
        public void Dispose()
        {
            if (_disposed)
            {
                return;
            }

            _disposed = true;

            // 释放作用域服务
            foreach (var service in _scopedInstances.Values)
            {
                (service as IDisposable)?.Dispose();
            }

            // 只有根容器才释放单例服务
            if (this == _rootContainer)
            {
                foreach (var service in _singletonInstances.Values)
                {
                    (service as IDisposable)?.Dispose();
                }
            }

            // 清空缓存
            _scopedInstances.Clear();
        }
    }

    // 服务作用域实现
    public class ServiceScope : IServiceScope
    {
        private readonly DIContainer _container;

        public ServiceScope(DIContainer container)
        {
            _container = container;
            ServiceProvider = container;
        }

        public IServiceProvider ServiceProvider { get; }

        public void Dispose()
        {
            _container.Dispose();
        }
    }

    // 属性注入特性
    [AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
    public class InjectAttribute : Attribute
    {
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336

# 容器设计说明:

  1. 服务缓存:
    • 使用ConcurrentDictionary保证线程安全
    • 为不同生命周期使用不同的缓存字典
    • 使用ServiceCacheKey支持多注册场景
  2. 生命周期管理:
    • Singleton:在根容器中缓存,所有作用域共享同一实例
    • Scoped:在当前作用域中缓存,同一作用域内复用
    • Transient:每次请求都创建新实例,不缓存
  3. 依赖解析策略:
    • 构造函数注入:自动选择最佳构造函数并解析其参数
    • 属性注入:通过[Inject]特性标记需要注入的属性
    • 集合注入:自动收集同一服务类型的多个实现
  4. 资源管理:
    • 实现IDisposable接口,作用域结束时自动释放资源
    • 区分根容器和子容器,避免重复释放

# 第七步:完善扩展方法

最后,我们添加一个扩展方法用于构建容器:

public static class ServiceCollectionExtensions
{
    // ... 前面的扩展方法 ...

    // 构建容器
    public static IServiceProvider BuildServiceProvider(this IServiceCollection services)
    {
        return new DIContainer(services);
    }
}
1
2
3
4
5
6
7
8
9
10

# 第八步:使用依赖注入容器

下面是一个完整的示例,展示如何使用我们的DI容器:

using CustomDI;
using System;

// 示例接口和实现
public interface ILogger
{
    void Log(string message);
}

public class ConsoleLogger : ILogger
{
    public void Log(string message)
    {
        Console.WriteLine($"[LOG] {message}");
    }
}

public interface IUserRepository
{
    void SaveUser(string username);
}

public class UserRepository : IUserRepository, IDisposable
{
    private readonly ILogger _logger;

    public UserRepository(ILogger logger)
    {
        _logger = logger;
        _logger.Log("UserRepository created");
    }

    public void SaveUser(string username)
    {
        _logger.Log($"User '{username}' saved");
    }

    public void Dispose()
    {
        Console.WriteLine("UserRepository disposed");
    }
}

public class UserService
{
    private readonly IUserRepository _repository;
    
    public UserService(IUserRepository repository)
    {
        _repository = repository;
    }
    
    [Inject]
    public ILogger Logger { get; set; }
    
    public void RegisterUser(string username)
    {
        Logger?.Log($"Registering user: {username}");
        _repository.SaveUser(username);
    }
}

class Program
{
    static void Main()
    {
        // 1. 创建服务集合
        var services = new ServiceCollection();
        
        // 2. 注册服务
        services.AddSingleton<ILogger, ConsoleLogger>();
        services.AddScoped<IUserRepository, UserRepository>();
        services.AddTransient<UserService>();
        
        // 3. 构建容器
        var rootProvider = services.BuildServiceProvider();
        
        // 4. 创建作用域
        using (var scope = rootProvider.CreateScope())
        {
            var scopedProvider = scope.ServiceProvider;
            
            // 5. 解析服务
            var userService = (UserService)scopedProvider.GetService(typeof(UserService));
            
            // 6. 使用服务
            userService.RegisterUser("john_doe");
            
            Console.WriteLine("First scope completed");
        } // 作用域结束,Scoped服务被释放
        
        // 创建另一个作用域
        using (var scope = rootProvider.CreateScope())
        {
            var userRepo = (IUserRepository)scope.ServiceProvider.GetService(typeof(IUserRepository));
            userRepo.SaveUser("jane_doe");
            
            Console.WriteLine("Second scope completed");
        }
        
        Console.WriteLine("Program completed");
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103

# 高级特性解释

# 1. 构造函数注入

原理:容器通过反射检查类的构造函数,自动提供所需的依赖项。

好处:

  • 依赖关系明确且不可变
  • 确保对象在创建时就获得所有必要依赖
  • 符合显式依赖原则

实现:

// 选择参数最多的构造函数
var constructor = constructors.OrderByDescending(c => c.GetParameters().Length).First();
var parameters = constructor.GetParameters();
var parameterInstances = new object[parameters.Length];

for (int i = 0; i < parameters.Length; i++)
{
    parameterInstances[i] = GetService(parameters[i].ParameterType);
    // 参数验证逻辑...
}

return constructor.Invoke(parameterInstances);
1
2
3
4
5
6
7
8
9
10
11
12

# 2. 属性注入

原理:容器通过反射查找标记了特定特性的属性,并设置这些属性的值。

好处:

  • 适用于可选依赖
  • 允许在构造函数之外注入依赖
  • 可以避免构造函数参数过多

实现:

foreach (var property in type.GetProperties(BindingFlags.Public | BindingFlags.Instance))
{
    var injectAttribute = property.GetCustomAttribute<InjectAttribute>();
    if (injectAttribute != null)
    {
        var propertyValue = GetService(property.PropertyType);
        if (propertyValue != null)
        {
            property.SetValue(instance, propertyValue);
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12

# 3. 生命周期管理

原理:根据服务的生命周期类型,决定何时创建新实例以及如何缓存实例。

实现三种生命周期的好处:

  • Singleton:节省资源,适用于无状态服务
  • Scoped:平衡资源使用和隔离性,适用于每个请求需要独立状态的服务
  • Transient:完全隔离,适用于有内部状态的服务

实现:

switch (descriptor.Lifetime)
{
    case ServiceLifetime.Singleton:
        return _rootContainer._singletonInstances.GetOrAdd(cacheKey, _ => CreateInstance(descriptor));
    
    case ServiceLifetime.Scoped:
        return _scopedInstances.GetOrAdd(cacheKey, _ => CreateInstance(descriptor));
    
    case ServiceLifetime.Transient:
        return CreateInstance(descriptor);
}
1
2
3
4
5
6
7
8
9
10
11

# 4. 服务集合注入

原理:自动收集并注入同一接口的多个实现。

好处:

  • 支持插件架构
  • 允许在不修改核心代码的情况下添加新功能
  • 简化多实现场景的处理

实现:

private object ResolveServices(Type elementType)
{
    // 获取所有实现
    if (!_serviceDescriptors.TryGetValue(elementType, out var descriptors))
    {
        return Array.CreateInstance(elementType, 0);
    }

    // 创建所有实例
    var instances = new List<object>();
    for (int i = 0; i < descriptors.Count; i++)
    {
        instances.Add(ResolveService(descriptors[i], i));
    }

    // 转换为数组
    var array = Array.CreateInstance(elementType, instances.Count);
    for (int i = 0; i < instances.Count; i++)
    {
        array.SetValue(instances[i], i);
    }

    return array;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

# 总结

我们已经成功实现了一个中等难度的依赖注入容器,它具有以下特性:

  1. 支持三种生命周期:Singleton、Scoped、Transient
  2. 支持多种注入方式:构造函数注入、属性注入
  3. 支持多种注册方式:类型注册、实例注册、工厂注册
  4. 支持作用域管理:创建和释放作用域
  5. 支持集合注入:自动收集同一接口的多个实现
  6. 资源管理:自动释放IDisposable服务

这个DI容器实现了核心功能,可以满足大多数应用场景的需求。它的设计借鉴了微软官方DI容器和Autofac的一些理念,但保持了实现的清晰和易于理解。

通过这个实现,您可以了解依赖注入容器的内部工作原理,以及各种设计决策背后的原因。这些知识将有助于您更好地使用DI容器,并在必要时进行定制或扩展。

编辑 (opens new window)
#asp.netcore
上次更新: 2026/03/05, 07:46:04
中间件基础

中间件基础→

最近更新
01
鉴权服务中心
03-11
02
聚合根
03-11
03
补充
02-06
更多文章>
Theme by Vdoing | Copyright © 2019-2026 moklgy's blog
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式