解决MySql布尔型新旧版本兼容问题,采用枚举来表示布尔型的数据表。由正向工程赋值
|
# ¶ÔÏóÈÝÆ÷ ObjectContainer
## ¼ò½é
`ObjectContainer` ÊÇ NewLife.Core ÖеÄÇáÁ¿¼¶¶ÔÏóÈÝÆ÷£¬Ö§³ÖÒÀÀµ×¢È루DI£©¹¦ÄÜ¡£Ìṩ¼òµ¥¶øÇ¿´óµÄ IoC ÈÝÆ÷¹¦ÄÜ£¬Ö§³Öµ¥Àý¡¢Ë²Ì¬ºÍ×÷ÓÃÓòÉúÃüÖÜÆÚ£¬¼æÈÝ `IServiceProvider` ½Ó¿Ú£¬¿ÉÒÔ×÷Ϊ ASP.NET Core ÄÚÖà DI µÄ²¹³ä»òÌæ´ú¡£
**ÃüÃû¿Õ¼ä**£º`NewLife.Model`
**ÎĵµµØÖ·**£ºhttps://newlifex.com/core/object_container
## ºËÐÄÌØÐÔ
- **ÇáÁ¿¼¶**£ºÎÞÍⲿÒÀÀµ£¬´úÂ뾫¼ò
- **ÈýÖÖÉúÃüÖÜÆÚ**£ºµ¥Àý£¨Singleton£©¡¢Ë²Ì¬£¨Transient£©¡¢×÷ÓÃÓò£¨Scoped£©
- **¹¹Ô캯Êý×¢Èë**£º×Ô¶¯½âÎö¹¹Ô캯Êý²ÎÊý£¬ÓÅÏÈÑ¡Ôñ²ÎÊý×î¶àµÄ¿ÉÆ¥Åä¹¹Ô캯Êý
- **¹¤³§Î¯ÍÐ**£ºÖ§³Ö×Ô¶¨ÒåʵÀý´´½¨Âß¼
- **È«¾ÖÈÝÆ÷**£ºÌṩ `ObjectContainer.Current` ºÍ `ObjectContainer.Provider` È«¾Ö·ÃÎÊ
- **±ê×¼¼æÈÝ**£ºÊµÏÖ `IServiceProvider` ½Ó¿Ú£¬Óë±ê×¼ DI ÈÝÆ÷»¥²Ù×÷
- **×÷ÓÃÓòÖ§³Ö**£ºÖ§³Ö `IServiceScope` ºÍ `IServiceScopeFactory`
## ¿ìËÙ¿ªÊ¼
```csharp
using NewLife.Model;
// »ñȡȫ¾ÖÈÝÆ÷
var ioc = ObjectContainer.Current;
// ×¢²á·þÎñ
ioc.AddSingleton<ILogger, ConsoleLogger>(); // µ¥Àý
ioc.AddTransient<IUserService, UserService>(); // ˲̬
ioc.AddScoped<IDbContext, MyDbContext>(); // ×÷ÓÃÓò
// ¹¹½¨·þÎñÌṩÕß
var provider = ioc.BuildServiceProvider();
// ½âÎö·þÎñ
var logger = provider.GetService<ILogger>();
var userService = provider.GetRequiredService<IUserService>();
```
## ºËÐÄÀàÐÍ
### IObjectContainer ½Ó¿Ú
¶ÔÏóÈÝÆ÷µÄºËÐĽӿڣ¬¶¨ÒåÁË·þÎñ×¢²áºÍ½âÎöµÄ»ù±¾ÄÜÁ¦¡£
| ³ÉÔ± | ÀàÐÍ | ˵Ã÷ |
|------|------|------|
| `Services` | `IList<IObject>` | ·þÎñ×¢²á¼¯ºÏ |
| `Register` | ·½·¨ | ×¢²áÀàÐͺÍÃû³Æ£¨Òѱê¼Ç EditorBrowsable.Never£© |
| `Add` | ·½·¨ | Ìí¼Ó·þÎñ×¢²á£¬ÔÊÐíÖØ¸´Ìí¼Óͬһ¸ö·þÎñ |
| `TryAdd` | ·½·¨ | ³¢ÊÔÌí¼Ó·þÎñ×¢²á£¬²»ÔÊÐíÖØ¸´Ìí¼Óͬһ¸ö·þÎñ |
| `GetService` | ·½·¨ | ½âÎöÀàÐ͵ÄʵÀý |
### ObjectLifetime ö¾Ù
¶¨Òå·þÎñµÄÉúÃüÖÜÆÚ²ßÂÔ¡£
| Öµ | ˵Ã÷ |
|------|------|
| `Singleton` | µ¥ÊµÀý£¬Õû¸öÓ¦ÓóÌÐòÉúÃüÖÜÆÚÄÚÖ»ÓÐÒ»¸öʵÀý |
| `Scoped` | ÈÝÆ÷ÄÚµ¥ÊµÀý£¬Í¬Ò»×÷ÓÃÓòÄÚ¹²ÏíʵÀý |
| `Transient` | ÿ´ÎÒ»¸öʵÀý£¬Ã¿´ÎÇëÇó¶¼´´½¨ÐÂʵÀý |
### IObject ½Ó¿Ú
¶ÔÏóÓ³Éä½Ó¿Ú£¬ÃèÊö·þÎñµÄÀàÐÍ¡¢ÊµÏÖºÍÉúÃüÖÜÆÚ¡£
| ³ÉÔ± | ÀàÐÍ | ˵Ã÷ |
|------|------|------|
| `ServiceType` | `Type` | ·þÎñÀàÐÍ£¬½Ó¿Ú»ò³éÏóÀàÀàÐÍ |
| `ImplementationType` | `Type?` | ʵÏÖÀàÐÍ£¬¾ßÌåʵÏÖÀàÀàÐÍ |
| `Lifetime` | `ObjectLifetime` | ÉúÃüÖÜÆÚ£¬¿ØÖÆÊµÀýµÄ´´½¨ºÍÏú»Ù²ßÂÔ |
### ServiceDescriptor Àà
·þÎñÃèÊö·û£¬ÊµÏÖ `IObject` ½Ó¿Ú£¬ÃèÊö·þÎñµÄÍêÕûÐÅÏ¢¡£
| ÊôÐÔ | ÀàÐÍ | ˵Ã÷ |
|------|------|------|
| `ServiceType` | `Type` | ·þÎñÀàÐÍ£¬Í¨³£Êǽӿڻò³éÏóÀà |
| `ImplementationType` | `Type?` | ʵÏÖÀàÐÍ£¬¾ßÌåµÄʵÏÖÀà |
| `Lifetime` | `ObjectLifetime` | ÉúÃüÖÜÆÚ |
| `Instance` | `Object?` | ·þÎñʵÀý£¬½öµ¥ÀýģʽÓÐЧ |
| `Factory` | `Func<IServiceProvider, Object>?` | ¶ÔÏ󹤳§£¬ÓÃÓÚ´´½¨·þÎñʵÀýµÄίÍÐ |
## API ²Î¿¼
### È«¾Ö·ÃÎÊ
#### Current
```csharp
public static IObjectContainer Current { get; set; }
```
È«¾ÖĬÈÏÈÝÆ÷ʵÀý£¬Ó¦ÓÃÆô¶¯Ê±×Ô¶¯´´½¨¡£
**ʾÀý**£º
```csharp
// ÔÚÈκεط½·ÃÎÊÈ«¾ÖÈÝÆ÷
var container = ObjectContainer.Current;
container.AddSingleton<IMyService, MyService>();
```
#### Provider
```csharp
public static IServiceProvider Provider { get; set; }
```
È«¾ÖĬÈÏ·þÎñÌṩÕߣ¬ÓÉ `Current` ÈÝÆ÷×Ô¶¯¹¹½¨¡£
**ʾÀý**£º
```csharp
// Ö±½Óͨ¹ýÈ«¾ÖÌṩÕß½âÎö·þÎñ
var service = ObjectContainer.Provider.GetService<IMyService>();
```
#### SetInnerProvider
```csharp
// ÉèÖÃÄÚ²¿·þÎñÌṩÕߣ¨ÓÃÓÚ UseXxx ½×¶Î£©
public static void SetInnerProvider(IServiceProvider innerServiceProvider)
// ÉèÖÃÄÚ²¿·þÎñÌṩÕß¹¤³§£¨ÓÃÓÚ AddXxx ½×¶ÎÑӳٰ󶨣©
public static void SetInnerProvider(Func<IServiceProvider> innerServiceProviderFactory)
```
ÓÃÓÚÓë ASP.NET Core µÈ¿ò¼ÜµÄ DI ÈÝÆ÷¼¯³É£¬ÊµÏÖÁ´Ê½²éÕÒ¡£µ± ObjectContainer ÖÐÕÒ²»µ½·þÎñʱ£¬»á×Ô¶¯´ÓÄÚ²¿ÌṩÕßÖвéÕÒ¡£
**ʾÀý**£º
```csharp
// ÔÚ Startup.Configure ÖÐÉèÖÃ
public void Configure(IApplicationBuilder app)
{
ObjectContainer.SetInnerProvider(app.ApplicationServices);
}
// »òÔÚ Program.cs ÖÐʹÓù¤³§ÑÓ³Ù°ó¶¨
ObjectContainer.SetInnerProvider(() => app.Services);
```
### ·þÎñ×¢²á
#### AddSingleton£¨µ¥Àý£©
```csharp
// ×¢²áÀàÐÍÓ³Éä
IObjectContainer AddSingleton<TService, TImplementation>()
IObjectContainer AddSingleton(Type serviceType, Type implementationType)
// ×¢²áʵÀý
IObjectContainer AddSingleton<TService>(TService? instance = null)
IObjectContainer AddSingleton(Type serviceType, Object? instance)
// ×¢²á¹¤³§
IObjectContainer AddSingleton<TService>(Func<IServiceProvider, TService> factory)
IObjectContainer AddSingleton(Type serviceType, Func<IServiceProvider, Object> factory)
```
×¢²áµ¥Àý·þÎñ£¬Õû¸öÓ¦ÓóÌÐòÉúÃüÖÜÆÚÖ»ÓÐÒ»¸öʵÀý¡£
**ʾÀý**£º
```csharp
var ioc = ObjectContainer.Current;
// ÀàÐÍÓ³Éä
ioc.AddSingleton<ILogger, FileLogger>();
// Ö±½Ó×¢²áʵÀý
var config = new AppConfig { Debug = true };
ioc.AddSingleton<AppConfig>(config);
// ¹¤³§Î¯ÍУ¨ÑÓ³Ù´´½¨£©
ioc.AddSingleton<IDbConnection>(sp =>
{
var config = sp.GetService<AppConfig>();
return new SqlConnection(config.ConnectionString);
});
// ×¢²á×ÔÉíÀàÐÍ£¨ÎÞÐè´«ÈëʵÀý£¬ÄÚ²¿×Ô¶¯ÊµÀý»¯£©
ioc.AddSingleton<MyService>();
```
#### AddTransient£¨Ë²Ì¬£©
```csharp
IObjectContainer AddTransient<TService, TImplementation>()
IObjectContainer AddTransient<TService>()
IObjectContainer AddTransient(Type serviceType, Type implementationType)
IObjectContainer AddTransient(Type serviceType, Func<IServiceProvider, Object> factory)
```
×¢²á˲̬·þÎñ£¬Ã¿´ÎÇëÇó¶¼´´½¨ÐÂʵÀý¡£
**ʾÀý**£º
```csharp
// ÿ´Î½âÎö¶¼´´½¨ÐÂʵÀý
ioc.AddTransient<IUserService, UserService>();
// ×ÔÉí×¢²á
ioc.AddTransient<OrderProcessor>();
// ¹¤³§Î¯ÍÐ
ioc.AddTransient<HttpClient>(sp => new HttpClient
{
BaseAddress = new Uri("https://api.example.com"),
Timeout = TimeSpan.FromSeconds(30)
});
```
#### AddScoped£¨×÷ÓÃÓò£©
```csharp
IObjectContainer AddScoped<TService, TImplementation>()
IObjectContainer AddScoped<TService>()
IObjectContainer AddScoped(Type serviceType, Type implementationType)
IObjectContainer AddScoped(Type serviceType, Func<IServiceProvider, Object> factory)
```
×¢²á×÷ÓÃÓò·þÎñ£¬Í¬Ò»×÷ÓÃÓòÄÚ¹²ÏíʵÀý¡£
**ʾÀý**£º
```csharp
// ͬһ×÷ÓÃÓò¹²Ïí
ioc.AddScoped<IDbContext, AppDbContext>();
// ¹¤³§Î¯ÍÐ
ioc.AddScoped<IUnitOfWork>(sp =>
{
var context = sp.GetService<IDbContext>();
return new UnitOfWork(context);
});
```
#### TryAdd ϵÁÐ
```csharp
// µ¥Àý
IObjectContainer TryAddSingleton<TService, TImplementation>()
IObjectContainer TryAddSingleton<TService>(TService? instance = null)
// ×÷ÓÃÓò
IObjectContainer TryAddScoped<TService, TImplementation>()
IObjectContainer TryAddScoped<TService>(TService? instance = null)
// ˲̬
IObjectContainer TryAddTransient<TService, TImplementation>()
IObjectContainer TryAddTransient<TService>(TService? instance = null)
```
³¢ÊÔÌí¼Ó·þÎñ£¬Èç¹ûÒÑ´æÔÚÏàͬ·þÎñÀàÐÍÔò²»Ìí¼Ó£¬·µ»Ø `false`¡£
**ʾÀý**£º
```csharp
// ½öÔÚδע²áʱÌí¼Ó
ioc.TryAddSingleton<ILogger, ConsoleLogger>();
// µÚ¶þ´ÎÌí¼Ó²»»áÉúЧ
ioc.TryAddSingleton<ILogger, FileLogger>(); // ±»ºöÂÔ
// Óà Add Ôò»áÌí¼Ó£¨×îºó×¢²áµÄÓÅÏÈ£©
ioc.AddSingleton<ILogger, FileLogger>(); // »áÌí¼Ó
```
### ·þÎñ¹¹½¨
#### BuildServiceProvider
```csharp
public static IServiceProvider BuildServiceProvider(this IObjectContainer container)
public static IServiceProvider BuildServiceProvider(this IObjectContainer container, IServiceProvider? innerServiceProvider)
```
´Ó¶ÔÏóÈÝÆ÷´´½¨·þÎñÌṩÕß¡£
**ʾÀý**£º
```csharp
var ioc = ObjectContainer.Current;
ioc.AddSingleton<IMyService, MyService>();
// »ù±¾¹¹½¨
var provider = ioc.BuildServiceProvider();
// ´øÄÚ²¿ÌṩÕߣ¨Á´Ê½²éÕÒ£©
var provider2 = ioc.BuildServiceProvider(existingProvider);
```
#### BuildHost
```csharp
public static IHost BuildHost(this IObjectContainer container)
public static IHost BuildHost(this IObjectContainer container, IServiceProvider? innerServiceProvider)
```
´Ó¶ÔÏóÈÝÆ÷´´½¨Ó¦ÓÃÖ÷»ú¡£
**ʾÀý**£º
```csharp
var ioc = ObjectContainer.Current;
ioc.AddSingleton<IMyService, MyService>();
var host = ioc.BuildHost();
host.Run();
```
### ·þÎñ½âÎö
#### GetService£¨»ù±¾½âÎö£©
```csharp
// IServiceProvider ½Ó¿Ú·½·¨
Object? GetService(Type serviceType)
// ·ºÐÍÀ©Õ¹·½·¨
T? GetService<T>(this IServiceProvider provider)
T? GetService<T>(this IObjectContainer container)
```
»ñÈ¡·þÎñʵÀý£¬Î´ÕÒµ½Ê±·µ»Ø null¡£½âÎöʱÓÅÏȲéÕÒ×îºó×¢²áµÄ·þÎñ¡£
**ʾÀý**£º
```csharp
var service = provider.GetService(typeof(IMyService));
var typedService = provider.GetService<IMyService>();
// Ö±½Ó´ÓÈÝÆ÷»ñÈ¡
var containerService = ioc.GetService<IMyService>();
```
#### GetRequiredService£¨±ØÒª½âÎö£©
```csharp
Object GetRequiredService(this IServiceProvider provider, Type serviceType)
T GetRequiredService<T>(this IServiceProvider provider)
```
»ñÈ¡±ØÒªµÄ·þÎñ£¬Î´ÕÒµ½Ê±Å׳ö `InvalidOperationException` Òì³£¡£
**ʾÀý**£º
```csharp
// Èç¹ûδע²á»áÅ׳öÒì³£
var config = provider.GetRequiredService<AppConfig>();
```
#### GetServices£¨ÅúÁ¿½âÎö£©
```csharp
IEnumerable<Object> GetServices(this IServiceProvider provider, Type serviceType)
IEnumerable<T> GetServices<T>(this IServiceProvider provider)
```
»ñȡָ¶¨ÀàÐ͵ÄËùÓзþÎñʵÀý£¨Ö§³Öͬһ·þÎñÀàÐ͵Ķà¸ö×¢²á£©¡£·µ»ØË³ÐòΪע²áµÄÄæÐò£¨×îºó×¢²áµÄ×îÏÈ·µ»Ø£©¡£
**ʾÀý**£º
```csharp
// ×¢²á¶à¸ö´¦ÀíÆ÷
ioc.AddSingleton<IMessageHandler, EmailHandler>();
ioc.AddSingleton<IMessageHandler, SmsHandler>();
ioc.AddSingleton<IMessageHandler, PushHandler>();
// »ñÈ¡ËùÓд¦ÀíÆ÷
var handlers = provider.GetServices<IMessageHandler>();
foreach (var handler in handlers)
{
handler.Handle(message);
}
```
### ×÷ÓÃÓòÖ§³Ö
#### IServiceScope ½Ó¿Ú
·¶Î§·þÎñ½Ó¿Ú£¬¸Ã·¶Î§ÉúÃüÖÜÆÚÄÚ£¬Ã¿¸ö·þÎñÀàÐÍÖ»ÓÐÒ»¸öʵÀý¡£
```csharp
public interface IServiceScope : IDisposable
{
IServiceProvider ServiceProvider { get; }
}
```
#### IServiceScopeFactory ½Ó¿Ú
·¶Î§·þÎñ¹¤³§½Ó¿Ú¡£
```csharp
public interface IServiceScopeFactory
{
IServiceScope CreateScope();
}
```
#### CreateScope
```csharp
IServiceScope? CreateScope(this IServiceProvider provider)
```
´´½¨·¶Î§×÷ÓÃÓò£¬¸Ã×÷ÓÃÓòÄÚ Scoped ·þÎñ¹²ÏíͬһʵÀý¡£
**ʾÀý**£º
```csharp
using var scope = provider.CreateScope();
var scopedService = scope.ServiceProvider.GetService<IDbContext>();
// scopedService ÔÚ´Ë×÷ÓÃÓòÄÚÊÇΨһµÄ
// ×÷ÓÃÓòÄÚÔٴλñÈ¡£¬·µ»ØÍ¬Ò»ÊµÀý
var scopedService2 = scope.ServiceProvider.GetService<IDbContext>();
// scopedService == scopedService2
```
#### CreateInstance
```csharp
Object? CreateInstance(this IServiceProvider provider, Type serviceType)
```
´´½¨·þÎñ¶ÔÏó£¬Ê¹Ó÷þÎñÌṩÕßÀ´Ìî³ä¹¹Ô캯Êý²ÎÊý¡£¿ÉÓÃÓÚ´´½¨Î´×¢²áÀàÐ͵ÄʵÀý¡£
**ʾÀý**£º
```csharp
// ´´½¨Î´×¢²áÀàÐ͵ÄʵÀý£¬×Ô¶¯×¢ÈëÒÑ×¢²áµÄÒÀÀµ
var instance = provider.CreateInstance(typeof(MyController));
```
## ÉúÃüÖÜÆÚÏê½â
### Singleton£¨µ¥Àý£©
```csharp
ioc.AddSingleton<IMyService, MyService>();
```
- **´´½¨Ê±»ú**£ºÊ×´ÎÇëÇóʱ´´½¨
- **ʵÀýÊýÁ¿**£ºÕû¸öÓ¦ÓóÌÐòÖ»ÓÐÒ»¸öʵÀý
- **ÊÍ·Åʱ»ú**£ºÓ¦ÓóÌÐò½áÊøÊ±ÊÍ·Å
- **ÊÊÓó¡¾°**£ºÅäÖá¢ÈÕÖ¾¡¢»º´æµÈÎÞ״̬»òÈ«¾Ö¹²ÏíµÄ·þÎñ
- **×¢ÒâÊÂÏî**£ºµ¥Àý·þÎñ²»Ó¦ÒÀÀµ×÷ÓÃÓò·þÎñ
### Transient£¨Ë²Ì¬£©
```csharp
ioc.AddTransient<IMyService, MyService>();
```
- **´´½¨Ê±»ú**£ºÃ¿´ÎÇëÇóʱ´´½¨
- **ʵÀýÊýÁ¿**£ºÃ¿´ÎÇëÇó¶¼ÊÇÐÂʵÀý
- **ÊÍ·Åʱ»ú**£ºÊ¹ÓÃÍê¼´¿É±» GC »ØÊÕ
- **ÊÊÓó¡¾°**£ºÇáÁ¿¼¶¡¢ÎÞ״̬µÄ·þÎñ
- **×¢ÒâÊÂÏî**£ºÆµ·±´´½¨¿ÉÄÜÓ°ÏìÐÔÄÜ
### Scoped£¨×÷ÓÃÓò£©
```csharp
ioc.AddScoped<IMyService, MyService>();
```
- **´´½¨Ê±»ú**£º×÷ÓÃÓòÄÚÊ×´ÎÇëÇóʱ´´½¨
- **ʵÀýÊýÁ¿**£ºÃ¿¸ö×÷ÓÃÓòÒ»¸öʵÀý
- **ÊÍ·Åʱ»ú**£º×÷ÓÃÓòÏú»ÙʱÊÍ·Å
- **ÊÊÓó¡¾°**£ºWeb ÇëÇó¡¢Êý¾Ý¿âÉÏÏÂÎĵÈ
- **×¢ÒâÊÂÏî**£ºÐèҪͨ¹ý `CreateScope()` ´´½¨×÷ÓÃÓò
## ¹¹Ô캯Êý×¢Èë
ObjectContainer Ö§³Ö×Ô¶¯¹¹Ô캯Êý×¢È룬ѡÔñ²ÎÊý×î¶àµÄ¿ÉÆ¥Åä¹¹Ô캯Êý£º
```csharp
public interface ILogger { void Log(String message); }
public class ConsoleLogger : ILogger
{
public void Log(String message) => Console.WriteLine(message);
}
public interface IRepository { }
public class UserRepository : IRepository
{
public ILogger Logger { get; }
// ¹¹Ô캯Êý×¢Èë
public UserRepository(ILogger logger)
{
Logger = logger;
}
}
public class UserService
{
public IRepository Repository { get; }
public ILogger Logger { get; }
// ¶à²ÎÊý¹¹Ô캯Êý
public UserService(IRepository repository, ILogger logger)
{
Repository = repository;
Logger = logger;
}
}
// ×¢²á·þÎñ
var ioc = ObjectContainer.Current;
ioc.AddSingleton<ILogger, ConsoleLogger>();
ioc.AddSingleton<IRepository, UserRepository>();
ioc.AddSingleton<UserService>();
// ½âÎöʱ×Ô¶¯×¢ÈëÒÀÀµ
var provider = ioc.BuildServiceProvider();
var userService = provider.GetService<UserService>();
// userService.Logger ºÍ userService.Repository ¶¼ÒÑ×Ô¶¯×¢Èë
```
### ¹¹Ô캯ÊýÑ¡Ôñ¹æÔò
1. »ñÈ¡ÀàÐ͵ÄËùÓй«¹²ÊµÀý¹¹Ô캯Êý
2. °´²ÎÊýÊýÁ¿½µÐòÅÅÁÐ
3. ÒÀ´Î³¢ÊÔÆ¥Å䣬ѡÔñµÚÒ»¸öËùÓвÎÊý¶¼ÄܽâÎöµÄ¹¹Ô캯Êý
4. »ù±¾ÀàÐͲÎÊý£¨Int32¡¢String¡¢Boolean µÈ£©Ê¹ÓÃĬÈÏÖµ
5. Èç¹ûûÓÐ¿ÉÆ¥ÅäµÄ¹¹Ô캯Êý£¬Å׳ö `InvalidOperationException`
### Ö§³ÖµÄĬÈϲÎÊýÀàÐÍ
| ÀàÐÍ | ĬÈÏÖµ |
|------|--------|
| `Boolean` | `false` |
| `Char` | `(Char)0` |
| `SByte`/`Byte` | `0` |
| `Int16`/`UInt16` | `0` |
| `Int32`/`UInt32` | `0` |
| `Int64`/`UInt64` | `0` |
| `Single`/`Double` | `0` |
| `Decimal` | `0` |
| `DateTime` | `DateTime.MinValue` |
| `String` | `null` |
## Óë ASP.NET Core ¼¯³É
### ·½Ê½Ò»£º×÷Ϊ²¹³äÈÝÆ÷
```csharp
// Program.cs
var builder = WebApplication.CreateBuilder(args);
// ʹÓà ASP.NET Core µÄ DI
builder.Services.AddControllers();
builder.Services.AddScoped<IUserService, UserService>();
var app = builder.Build();
// ÉèÖÃÄÚ²¿ÌṩÕߣ¬ÊµÏÖÁ´Ê½²éÕÒ
ObjectContainer.SetInnerProvider(app.Services);
// ÏÖÔÚ ObjectContainer.Provider ¿ÉÒÔ½âÎö ASP.NET Core ×¢²áµÄ·þÎñ
var userService = ObjectContainer.Provider.GetService<IUserService>();
```
### ·½Ê½¶þ£ºÑÓ³Ù°ó¶¨
```csharp
// ÔÚ AddXxx ½×¶ÎʹÓù¤³§ÑÓ³Ù°ó¶¨
ObjectContainer.SetInnerProvider(() => app.Services);
```
### ·½Ê½Èý£º»ìºÏʹÓÃ
```csharp
// ÔÚ NewLife ÈÝÆ÷ÖÐ×¢²á
ObjectContainer.Current.AddSingleton<ICache, MemoryCache>();
// ÔÚ ASP.NET Core ÖÐÒ²¿ÉÒÔ·ÃÎÊ
builder.Services.AddSingleton(sp =>
ObjectContainer.Provider.GetService<ICache>()!);
```
## ʵսʾÀý
### 1. ¿ØÖÆÌ¨Ó¦ÓÃ
```csharp
public class Program
{
public static void Main()
{
var ioc = ObjectContainer.Current;
// ×¢²á·þÎñ
ioc.AddSingleton<ILogger, ConsoleLogger>();
ioc.AddSingleton<IConfiguration, JsonConfiguration>();
ioc.AddTransient<IUserService, UserService>();
// ¹¹½¨²¢ÔËÐÐ
var provider = ioc.BuildServiceProvider();
var service = provider.GetRequiredService<IUserService>();
service.Process();
}
}
```
### 2. Web Ó¦ÓÃ
```csharp
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
// ½« NewLife ÈÝÆ÷µÄ×¢²áͬ²½µ½ ASP.NET Core
var ioc = ObjectContainer.Current;
ioc.AddSingleton<IMyService, MyService>();
// ¸´ÖƵ½ ASP.NET Core ÈÝÆ÷
foreach (var item in ioc.Services)
{
// ת»»²¢Ìí¼Óµ½ services
}
}
}
```
### 3. ²å¼þϵͳ
```csharp
public class PluginLoader
{
private readonly IObjectContainer _container;
public PluginLoader()
{
_container = new ObjectContainer();
}
public void LoadPlugins(String pluginPath)
{
var assemblies = Directory.GetFiles(pluginPath, "*.dll")
.Select(Assembly.LoadFrom);
foreach (var assembly in assemblies)
{
var pluginTypes = assembly.GetTypes()
.Where(t => typeof(IPlugin).IsAssignableFrom(t) && !t.IsAbstract);
foreach (var type in pluginTypes)
{
_container.AddTransient(typeof(IPlugin), type);
}
}
}
public IEnumerable<IPlugin> GetPlugins()
{
var provider = _container.BuildServiceProvider();
return provider.GetServices<IPlugin>();
}
}
```
### 4. µ¥Ôª²âÊÔ
```csharp
[TestClass]
public class UserServiceTests
{
private IServiceProvider _provider;
[TestInitialize]
public void Setup()
{
var ioc = new ObjectContainer();
// ×¢²á Mock ·þÎñ
ioc.AddSingleton<ILogger>(new MockLogger());
ioc.AddSingleton<IRepository>(new MockRepository());
ioc.AddTransient<IUserService, UserService>();
_provider = ioc.BuildServiceProvider();
}
[TestMethod]
public void TestCreateUser()
{
var service = _provider.GetRequiredService<IUserService>();
var result = service.CreateUser("test");
Assert.IsNotNull(result);
}
}
```
## ¸ß¼¶Ó÷¨
### ·þÎñÌæ»»
ʹÓà `Add` ·½·¨¿ÉÒÔÖØ¸´×¢²áͬһ·þÎñÀàÐÍ£¬½âÎöʱ·µ»Ø×îºó×¢²áµÄ£º
```csharp
ioc.AddSingleton<ILogger, ConsoleLogger>();
ioc.AddSingleton<ILogger, FileLogger>(); // Ìæ»»
var logger = provider.GetService<ILogger>(); // ·µ»Ø FileLogger
```
### Ìõ¼þ×¢²á
ʹÓà `TryAdd` ʵÏÖÌõ¼þ×¢²á£º
```csharp
// ½öÔÚδע²áʱÌí¼ÓĬÈÏʵÏÖ
ioc.TryAddSingleton<ILogger, ConsoleLogger>();
// Óû§¿ÉÒÔÔÚ´Ë֮ǰע²á×Ô¼ºµÄʵÏÖ
```
### ¹¤³§Ä£Ê½
```csharp
ioc.AddSingleton<IConnectionFactory>(sp =>
{
var config = sp.GetRequiredService<IConfiguration>();
var connStr = config["Database:ConnectionString"];
return new SqlConnectionFactory(connStr);
});
```
### ×°ÊÎÆ÷ģʽ
```csharp
// ×¢²á»ù´¡ÊµÏÖ
ioc.AddSingleton<ILogger, ConsoleLogger>();
// ×¢²á×°ÊÎÆ÷
ioc.AddSingleton<ILogger>(sp =>
{
var services = sp.GetServices<ILogger>().ToList();
var inner = services.Count > 1 ? services[1] : services[0];
return new LoggingDecorator(inner);
});
```
## ×î¼Ñʵ¼ù
### ÍÆ¼ö
1. **ÓÅÏÈʹÓýӿÚ×¢²á**£º±ãÓÚ²âÊÔºÍÌæ»»ÊµÏÖ
2. **ºÏÀíÑ¡ÔñÉúÃüÖÜÆÚ**£ºµ¥ÀýÓÃÓÚÎÞ״̬·þÎñ£¬×÷ÓÃÓòÓÃÓÚÓÐ״̬µ«ÐèÒª¹²ÏíµÄ·þÎñ
3. **ʹÓà TryAdd ·ÀÖ¹¸²¸Ç**£º¿â´úÂëÖÐʹÓà TryAdd ÔÊÐíÓû§×Ô¶¨ÒåʵÏÖ
4. **ÔçÆÚ×¢²á£¬ÑÓ³Ù½âÎö**£ºÔÚÓ¦ÓÃÆô¶¯Ê±Íê³ÉËùÓÐ×¢²á
### ±ÜÃâ
1. **±ÜÃâ·þÎñ¶¨Î»Æ÷ģʽ**£º²»ÒªÔÚÒµÎñ´úÂëÖÐÖ±½Óµ÷Óà `ObjectContainer.Provider`
2. **±ÜÃâµ¥ÀýÒÀÀµ×÷ÓÃÓò**£ºµ¥Àý·þÎñ²»Ó¦ÒÀÀµ×÷ÓÃÓò·þÎñ
3. **±ÜÃâÑ»·ÒÀÀµ**£ºA ÒÀÀµ B£¬B ÒÀÀµ A »áµ¼Ö½âÎöʧ°Ü
4. **±ÜÃâÔÚÈȵã·¾¶×¢²á**£º·þÎñ×¢²áÓ¦ÔÚÆô¶¯Ê±Íê³É
### ÉúÃüÖÜÆÚÑ¡Ôñ½¨Òé
```csharp
// ÅäÖá¢ÈÕÖ¾ ¡ú µ¥Àý
ioc.AddSingleton<AppConfig>();
ioc.AddSingleton<ILogger, FileLogger>();
// Êý¾Ý¿âÉÏÏÂÎÄ ¡ú ×÷ÓÃÓò£¨Web£©»ò˲̬£¨¿ØÖÆÌ¨£©
ioc.AddScoped<IDbContext, AppDbContext>(); // Web
ioc.AddTransient<IDbContext, AppDbContext>(); // ¿ØÖÆÌ¨
// ÒµÎñ·þÎñ¶ÔÏó ¡ú ˲̬
ioc.AddTransient<IValidator, UserValidator>();
```
## ³£¼ûÎÊÌâ
### Q: ½âÎö·þÎñʱÅ׳ö "No suitable constructor" Òì³£
**ÔÒò**£º¹¹Ô캯ÊýµÄij¸ö²ÎÊýÀàÐÍδע²á¡£
**½â¾ö**£º
```csharp
// ¼ì²é²¢×¢²áËùÓÐÒÀÀµ
ioc.AddSingleton<IDependency, Dependency>();
```
### Q: Scoped ·þÎñÔÚµ¥ÀýÖÐÎÞ·¨ÕýÈ·¹¤×÷
**ÔÒò**£ºµ¥Àý·þÎñµÄÉúÃüÖÜÆÚ±È×÷ÓÃÓò³¤£¬»á³ÖÓйýÆÚµÄ×÷ÓÃÓòʵÀý¡£
**½â¾ö**£º
```csharp
// ¸ÄÓù¤³§Ä£Ê½
ioc.AddSingleton<IServiceFactory>(sp =>
new ServiceFactory(() => sp.CreateScope()));
```
### Q: ͬһ½Ó¿Ú×¢²á¶à¸öʵÏÖ£¬Ö»ÄÜ»ñȡһ¸ö
**ÔÒò**£º`GetService<T>()` Ö»·µ»Ø×îºó×¢²áµÄʵÏÖ¡£
**½â¾ö**£º
```csharp
// ʹÓà GetServices »ñÈ¡ËùÓÐʵÏÖ
var services = provider.GetServices<IHandler>();
```
### Q: ÈçºÎÓë ASP.NET Core DI ¹²´æ
**½â¾ö**£ºÊ¹Óà `SetInnerProvider` ½¨Á¢Á´Ê½²éÕÒ£º
```csharp
ObjectContainer.SetInnerProvider(app.Services);
```
## Óë Microsoft.Extensions.DependencyInjection ¶Ô±È
| ÌØÐÔ | ObjectContainer | MS DI |
|------|-----------------|-------|
| ÒÀÀµ´óС | ¼«Ð¡£¨ÎÞÒÀÀµ£© | ÐèÒª¶îÍâ°ü |
| ÉúÃüÖÜÆÚ | Ö§³Ö | Ö§³Ö |
| ¹¹Ô캯Êý×¢Èë | Ö§³Ö | Ö§³Ö |
| ÊôÐÔ×¢Èë | ²»Ö§³Ö | ²»Ö§³Ö |
| ·½·¨×¢Èë | ²»Ö§³Ö | ²»Ö§³Ö |
| ×°ÊÎÆ÷ģʽ | ÊÖ¶¯Ö§³Ö | Ö§³Ö |
| ÑéÖ¤ | ÎÞ | Ö§³Ö |
| È«¾Ö·ÃÎÊ | ÄÚÖà | ÐèÒª×ÔÐÐʵÏÖ |
## Ïà¹ØÁ´½Ó
- [NewLife.Core ÏîÄ¿Ö÷Ò³](https://github.com/NewLifeX/X)
- [ÔÚÏßÎĵµ](https://newlifex.com/core/object_container)
- [Ó¦ÓÃÖ÷»ú IHost](/NewLife/X/Blob/master/Doc/./Ó¦ÓÃÖ÷»úHost.md)
|