C# , .netWebApi 实现类似Java 的Ioc 自动装配@Autowired
写C# 一直很羡慕Java的@Autowired 自动装配. 因为C# 必须手动在Ioc里注册,
例如
builder.Services.AddSingleton<IHostedService, StartupInitializationService>();
但是我们也可以用C# 的反射机制 , 用接口实现自动装配. 写接口, 扩展方法如下:
namespace MyFanucApi.Service.Ioc
{public interface IScoped{}
}
namespace MyFanucApi.Service.Ioc
{public interface ISingleton{}
}
namespace MyFanucApi.Service.Ioc
{public interface ITransient{}
}
using System.Reflection;namespace MyFanucApi.Service.Ioc
{public static class AutoRegister{public static IServiceCollection RegisterAllServices(this IServiceCollection services){//获取当前程序集var entryAssembly = Assembly.GetEntryAssembly();//获取所有类型//!. null包容运算符,当你明确知道表达式的值不为null 使用!.(即null包容运算符)可以告知编译器这是预期行为,不应发出警告//例: entryAssembly!.GetReferencedAssemblies() 正常//entryAssembly.GetReferencedAssemblies() 编译器判断entryAssembly有可能为null,变量下方出现绿色波浪线警告var types = entryAssembly!.GetReferencedAssemblies()//获取当前程序集所引用的外部程序集.Select(Assembly.Load)//装载.Concat(new List<Assembly>() { entryAssembly })//与本程序集合并.SelectMany(x => x.GetTypes())//获取所有类.Distinct();//排重//三种生命周期分别注册Register<ITransient>(types, services.AddTransient, services.AddTransient);Register<IScoped>(types, services.AddScoped, services.AddScoped);Register<ISingleton>(types, services.AddSingleton, services.AddSingleton);return services;}/// <summary>/// 根据服务标记的生命周期interface,不同生命周期注册到容器里面/// </summary>/// <typeparam name="TLifetime">注册的生命周期</typeparam>/// <param name="types">集合类型</param>/// <param name="register">委托:成对注册</param>/// <param name="registerDirectly">委托:直接注册服务实现</param>private static void Register<TLifetime>(IEnumerable<Type> types, Func<Type, Type, IServiceCollection> register, Func<Type, IServiceCollection> registerDirectly){//找到所有标记了Tlifetime生命周期接口的实现类var tImplements = types.Where(x => x.IsClass && !x.IsAbstract && x.GetInterfaces().Any(tinterface => tinterface == typeof(TLifetime)));//遍历,挨个以其他所有接口为key,当前实现为value注册到容器中foreach (var t in tImplements){//获取除生命周期接口外的所有其他接口var interfaces = t.GetInterfaces().Where(x => x != typeof(TLifetime));if (interfaces.Any()){foreach (var i in interfaces){register(i, t);}}//有时需要直接注入实现类本身registerDirectly(t);}}}
}
在Ioc中注册:
//自动注入
builder.Services.RegisterAllServices();
这样, 凡是实现接口IScoped , ISingleton 的类都在Ioc中自动注册了
C# , .netWebApi 实现类似Java 的Ioc 自动装配@Autowired
写C# 一直很羡慕Java的@Autowired 自动装配. 因为C# 必须手动在Ioc里注册,
例如
builder.Services.AddSingleton<IHostedService, StartupInitializationService>();
但是我们也可以用C# 的反射机制 , 用接口实现自动装配. 写接口, 扩展方法如下:
namespace MyFanucApi.Service.Ioc
{public interface IScoped{}
}
namespace MyFanucApi.Service.Ioc
{public interface ISingleton{}
}
namespace MyFanucApi.Service.Ioc
{public interface ITransient{}
}
using System.Reflection;namespace MyFanucApi.Service.Ioc
{public static class AutoRegister{public static IServiceCollection RegisterAllServices(this IServiceCollection services){//获取当前程序集var entryAssembly = Assembly.GetEntryAssembly();//获取所有类型//!. null包容运算符,当你明确知道表达式的值不为null 使用!.(即null包容运算符)可以告知编译器这是预期行为,不应发出警告//例: entryAssembly!.GetReferencedAssemblies() 正常//entryAssembly.GetReferencedAssemblies() 编译器判断entryAssembly有可能为null,变量下方出现绿色波浪线警告var types = entryAssembly!.GetReferencedAssemblies()//获取当前程序集所引用的外部程序集.Select(Assembly.Load)//装载.Concat(new List<Assembly>() { entryAssembly })//与本程序集合并.SelectMany(x => x.GetTypes())//获取所有类.Distinct();//排重//三种生命周期分别注册Register<ITransient>(types, services.AddTransient, services.AddTransient);Register<IScoped>(types, services.AddScoped, services.AddScoped);Register<ISingleton>(types, services.AddSingleton, services.AddSingleton);return services;}/// <summary>/// 根据服务标记的生命周期interface,不同生命周期注册到容器里面/// </summary>/// <typeparam name="TLifetime">注册的生命周期</typeparam>/// <param name="types">集合类型</param>/// <param name="register">委托:成对注册</param>/// <param name="registerDirectly">委托:直接注册服务实现</param>private static void Register<TLifetime>(IEnumerable<Type> types, Func<Type, Type, IServiceCollection> register, Func<Type, IServiceCollection> registerDirectly){//找到所有标记了Tlifetime生命周期接口的实现类var tImplements = types.Where(x => x.IsClass && !x.IsAbstract && x.GetInterfaces().Any(tinterface => tinterface == typeof(TLifetime)));//遍历,挨个以其他所有接口为key,当前实现为value注册到容器中foreach (var t in tImplements){//获取除生命周期接口外的所有其他接口var interfaces = t.GetInterfaces().Where(x => x != typeof(TLifetime));if (interfaces.Any()){foreach (var i in interfaces){register(i, t);}}//有时需要直接注入实现类本身registerDirectly(t);}}}
}
在Ioc中注册:
//自动注入
builder.Services.RegisterAllServices();
这样, 凡是实现接口IScoped , ISingleton 的类都在Ioc中自动注册了