.net6之AutoInjection
概念
依赖注入私有化封装
区别:
AddTransient:每次 service 请求都是获得不同的实例。暂时性模式:暂时性对象始终不同,无论是不是同一个请求(同一个请求里的不同服务)同一个客户端,每次都是创建新的实例。
AddScoped:对于同一个请求返回同一个实例,不同的请求返回不同的实例。作用域模式:作用域对象在一个客户端请求中是相同的,但在多个客户端请求中是不同的。
AddSingleton:每次都是获得同一个实例。单一实例模式:单一实例对象对每个对象和每个请求都是相同的,可以说是不同客户端不同请求都是相同的。
生命周期:
AddSingleton的生命周期:项目启动-项目关闭 相当于静态类 只会有一个。
AddScoped的生命周期:请求开始-请求结束 在这次请求中获取的对象都是同一个。
AddTransient的生命周期:请求获取-(GC回收-主动释放) 每一次获取的对象都不是同一。
项目总览
实现
程序集管理 AssemblyManager
public static class AssemblyManager
{
private static readonly string[] Filters = { "dotnet-", "Microsoft.", "mscorlib", "netstandard", "System", "Windows" };
private static Assembly[] _allAssemblies;
private static Type[] _allTypes;
static AssemblyManager()
{
AssemblyFilterFunc = name =>
{
return name.Name != null && !Filters.Any(m => name.Name.StartsWith(m));
};
}
/// 设置 程序集过滤器
/// </summary>
public static Func<AssemblyName, bool> AssemblyFilterFunc { private get; set; }
/// <summary>
/// 获取 所有类型
/// </summary>
public static Type[] AllTypes
{
get
{
if (_allTypes == null)
{
Init();
}
return _allTypes;
}
}
/// <summary>
/// 初始化
/// </summary>
public static void Init()
{
_allAssemblies = DependencyContext.Default.GetDefaultAssemblyNames().Where(AssemblyFilterFunc).Select(Assembly.Load).ToArray();
_allTypes = _allAssemblies.SelectMany(m => m.GetTypes()).Distinct().ToArray();
}
/// <summary>
/// 查找指定条件的类型
/// </summary>
public static Type[] FindTypes(Func<Type, bool> predicate)
{
return AllTypes.Where(predicate).Distinct().ToArray();
}
}
AutoInjectionAttribute
/// <summary>
/// 自动注入依赖标记
/// </summary>
[AttributeUsage(AttributeTargets.Class,Inherited =false)]
public abstract class AutoInjectionAttribute:Attribute
{
/// <summary>
/// 注入类型
/// </summary>
public ServiceLifetime InjectionType { get; }
protected AutoInjectionAttribute(ServiceLifetime lifestyle) => InjectionType = lifestyle;
/// <summary>
/// 注入当前实现接口,默认为true
/// </summary>
public bool AddImplementedInterface { get; set; } = true;
/// <summary>
/// 尝试添加
/// </summary>
public bool TryAdd { get; set; }
/// <summary>
/// 是否替换已存在的服务实现
/// </summary>
public bool Replace { get; set; }
/// <summary>
/// 是否注册自身类型,默认没有接口的类型会注册自身
/// </summary>
public bool AddSelf { get; set; }
}
AutoInjectionMultipleAttribute
/// <summary>
/// 标记允许多重注入,即一个接口可以注入多个实例
/// </summary>
[AttributeUsage(AttributeTargets.Interface, Inherited = false)]
public class AutoInjectionMultipleAttribute : Attribute
{
}
IgnoreAutoInjectionAttribute
/// <summary>
/// 设置此标记类型,将不会被自动添加依赖注册
/// </summary>
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, Inherited = false)]
public class IgnoreAutoInjectionAttribute : Attribute
{
}
IInjectionConfiguration
[IgnoreAutoInjection]
public interface IInjectionConfiguration
{
void Configuration(IServiceCollection services);
}
IInjectionScoped
/// <summary>
/// 实现此接口的类型将被注册为<see cref="ServiceLifetime.Scoped"/>模式
/// </summary>
[IgnoreAutoInjection]
public interface IInjectionScoped
{
}
IInjectionSingleton
/// <summary>
/// 实现此接口的类型将被注册为<see cref="ServiceLifetime.Singleton">
/// </summary>
[IgnoreAutoInjection]
public interface IInjectionSingleton
{
}
IInjectionTransient
/// <summary>
/// 实现此接口的类型将被注册为<see cref="ServiceLifetime.Transient"/>模式
/// </summary>
[IgnoreAutoInjection]
public interface IInjectionTransient
{
}
ServiceCollectionExtensions(服务封装)
public static class ServiceCollectionExtensions
{
public static IServiceCollection AddAutoInjection(this IServiceCollection services)
{
Type[] autoInjectionImplementedTypes = FindAutoInjectionImplementedTypes();
autoInjectionImplementedTypes.Each(implementationType => AddToServiceCollection(services, implementationType));
foreach (Type module in AssemblyManager.FindTypes(type =>
type.IsClass && !type.IsAbstract && !type.IsInterface &&
!type.HasAttribute<IgnoreAutoInjectionAttribute>() && type.GetInterfaces().Contains(typeof(IInjectionConfiguration))))
{
((IInjectionConfiguration)Activator.CreateInstance(module)).Configuration(services);
}
return services;
}
#region 将服务实现类型注册到服务集合中
private static void AddToServiceCollection(IServiceCollection services, Type implementationType)
{
if (implementationType.IsAbstract || implementationType.IsInterface)
{
return;
}
ServiceLifetime? lifetime =GetLifeTimeType(implementationType);
if (lifetime == null)
{
return;
}
var injectionAttribute = implementationType.GetAttribute<AutoInjectionAttribute>();
// implementationType.GetMethods().Each(m =>m.)
Type[] serviceTypes = (injectionAttribute == null || injectionAttribute.AddImplementedInterface) ? GetTmplementedInterfaces(implementationType) : null;
//服务数量为0或显示要求注册自身时,注册自身
if (serviceTypes.HasVal() == false || injectionAttribute?.AddSelf==true)
{
services.TryAdd(new ServiceDescriptor(implementationType, implementationType, lifetime.Value));
if (serviceTypes.HasVal() == false)
{
return;
}
}
if (serviceTypes.Length > 1)
{
List<string> orderTokens=new List<string> { implementationType.Namespace.Substring("",".","") };
orderTokens.AddIfNotExist("BPA");
serviceTypes = serviceTypes.OrderByPrefixes(m => m.FullName, orderTokens.ToArray()).ToArray();
}
//注册接口服务
for (int i = 0; i < serviceTypes.Length; i++)
{
Type serviceType = serviceTypes[i];
ServiceDescriptor descriptor = new ServiceDescriptor(serviceType, implementationType, lifetime.Value);
if (lifetime.Value == ServiceLifetime.Transient)
{
services.TryAddEnumerable(descriptor);
continue;
}
bool multiple = serviceType.HasAttribute<AutoInjectionMultipleAttribute>();
if (i == 0)
{
if (multiple)
{
services.Add(descriptor);
}
else
{
AddSingleService(services, descriptor, injectionAttribute);
}
}
else
{
if (multiple)
{
services.Add(descriptor);
}
else
{
//有多个接口,后边的接口注册使用第一个接口的实例,保证同个实现类的多个接口获得同一实例
Type firstServiceType = serviceTypes[0];
descriptor = new ServiceDescriptor(serviceType, provider => provider.GetService(firstServiceType), lifetime.Value);
AddSingleService(services, descriptor, injectionAttribute);
}
}
}
}
#endregion
#region 查找所有自动注册的服务实现类型
static Type[] FindAutoInjectionImplementedTypes()
{
Type[] types = new[] { typeof(IInjectionScoped), typeof(IInjectionSingleton), typeof(IInjectionTransient) };
return AssemblyManager.FindTypes(type=>type.IsClass&&!type.IsAbstract&&!type.IsInterface&&
!type.HasAttribute<IgnoreAutoInjectionAttribute>()&&
(types.Any(t => t.IsAssignableFrom(type)||type.HasAttribute<AutoInjectionAttribute>(false))));
}
#endregion
#region 获取服务注册生命周期
static ServiceLifetime? GetLifeTimeType(Type type)
{
var attribute=type.GetAttribute<AutoInjectionAttribute>();
if (attribute != null)
{
return attribute.InjectionType;
}
if (type.IsDericeClassFrom<IInjectionTransient> != null)
{
return ServiceLifetime.Transient;
}
if (type.IsDericeClassFrom<IInjectionScoped> != null)
{
return ServiceLifetime.Scoped;
}
if (type.IsDericeClassFrom<IInjectionSingleton> != null)
{
return ServiceLifetime.Singleton;
}
return null;
}
#endregion
#region 获取实现类型的所有可注册服务接口
static Type[] GetTmplementedInterfaces(Type implementationType)
{
Type[] exceptInterfaces = { typeof(IDisposable) };
Type[] interfaceTypes=implementationType.GetInterfaces().Where(t =>! exceptInterfaces.Contains(t)&&!t.HasAttribute<IgnoreAutoInjectionAttribute>()).ToArray();
for (int index = 0; index < interfaceTypes.Length; index++)
{
Type interfaceType = interfaceTypes[index];
if (interfaceType.IsGenericType && !interfaceType.IsGenericTypeDefinition && interfaceType.FullName == null)
{
exceptInterfaces[index] = interfaceType.GetGenericTypeDefinition();
}
}
return interfaceTypes;
}
#endregion
#region 注册单例服务
/// <summary>
/// 注册单例服务
/// </summary>
/// <param name="services"></param>
/// <param name="descriptor"></param>
/// <param name="injectionAttribute"></param>
static void AddSingleService(IServiceCollection services, ServiceDescriptor descriptor, AutoInjectionAttribute injectionAttribute)
{
if (injectionAttribute?.Replace == true)
{
services.Replace(descriptor);
}
else if (injectionAttribute?.TryAdd == true)
{
services.TryAdd(descriptor);
}
else
{
services.Add(descriptor);
}
}
#endregion
}
打包传送门 https://www.cnblogs.com/inclme/p/16053978.html
.net6中使用
引用上述nuget包
var builder = WebApplication.CreateBuilder(args);
//自动扫描依赖注入
builder.Services.AddAutoInjection();
封装AppService 统一封装数据库上下分封装和参数注入 ORM可替换成其他的
public abstract class AppService : AppServiceBase<UserIdentityBase>
{
public AppService(IServiceProvider serviceProvider) : base(serviceProvider)
{
_sqlSugarClient = ResolveService<SqlSugarScope>();
_configurationModel = ResolveService<IOptions<ConfigurationModel>>();
}
protected SqlSugarScope _sqlSugarClient { get; }
protected IOptions<ConfigurationModel> _configurationModel { get; }
}
服务自动注入示例
public interface IAuthorizeService : IInjectionScoped
{
Task<JwtInfo> SignInAsync(SignInRequest request);
Task<UserIdentityResponse> GetUserInfoAsync();
}
public class AuthorizeService : AppService, IAuthorizeService
{
private readonly IJwtService _jwtService;
public AuthorizeService(IJwtService jwtService, IServiceProvider serviceProvider) : base(serviceProvider)
{
_jwtService = jwtService;
}
#region 用户登录
/// <summary>
/// 用户登录
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
public async Task<JwtInfo> SignInAsync(SignInRequest request)
{
request.Pwd = EncryptHelper.DesEncrypt(request.Pwd, "~1@Aa*<>");
var token = _jwtService.CreateAccessToken(new BPAUserIdentity()
{
Id = IdGenerator.NextId(),
UserName = request.UserName
});
return await Task.FromResult(token);
}
#endregion
#region 获取用户信息
/// <summary>
/// 获取用户信息
/// </summary>
/// <returns></returns>
public async Task<UserIdentityResponse> GetUserInfoAsync()
{
UserIdentityResponse res = new UserIdentityResponse();
res.Id = CurrentUser.Id;
res.UserName = CurrentUser.UserName;
return await Task.FromResult(res);
}
#endregion
}