写C# 一直很羡慕Java的@Autowired 自动装配. 因为C# 必须手动在Ioc里注册
之前用接口实现了自动注册IOC, 总是觉得美中不足, 毕竟没有真正实现用注解/特性实现自动注入, 这次我们来实现一个用特性注入Ioc的扩展方法.
csharp
namespace MyCode.BLL.Service.Ioc
{
/// <summary>
/// 类型的生命周期枚举
/// </summary>
public enum Lifetime
{
/// <summary>
/// 单例
/// </summary>
Singleton,
/// <summary>
/// 多例
/// </summary>
Transient,
Scoped
}
/// <summary>
/// 标注类型的生命周期、是否自动初始化
/// </summary>
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class ExposedServiceAttribute : Attribute
{
public Lifetime Lifetime { get; set; }
public bool AutoInitialize { get; set; }
public Type[] Types { get; set; }
public ExposedServiceAttribute(Lifetime lifetime = Lifetime.Transient, params Type[] types)
{
Lifetime = lifetime;
Types = types;
}
}
}
csharp
using Microsoft.Extensions.DependencyInjection;
using MyCode.BLL.Service.Ioc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace MyCode.Utils.AttributeIoc
{
public static class DependencyExtension
{
/// <summary>
/// 获取class, 非抽象类, 特性有ExposedServiceAttribute 注解
/// </summary>
/// <param name="services"></param>
/// <returns></returns>
//private static List<Type> GetTypes(Assembly assembly)
//{
// var result = assembly
// .GetTypes()
// .Where(
// t =>
// t != null
// && t.IsClass
// && !t.IsAbstract
// && t.CustomAttributes.Any(
// p => p.AttributeType == typeof(ExposedServiceAttribute)
// )
// )
// .ToList();
// return result;
//}
private static List<Type> MyGetTypes()
{
//获取当前程序集
var entryAssembly = Assembly.GetEntryAssembly();
var types = entryAssembly!
.GetReferencedAssemblies() //获取当前程序集所引用的外部程序集
.Select(Assembly.Load) //装载
.Concat(new List<Assembly>() { entryAssembly }) //与本程序集合并
.SelectMany(x => x.GetTypes()) //获取所有类
.Where(
t =>
t != null
&& t.IsClass
&& !t.IsAbstract
&& t.CustomAttributes.Any(
p => p.AttributeType == typeof(ExposedServiceAttribute)
)
)
.Distinct() //排重
.ToList();
;
return types;
}
//public static void RegisterAssembly(this IServiceCollection services, Assembly assembly)
//{
// var list = GetTypes(assembly);
// foreach (var type in list)
// {
// RegisterAssembly(services, type);
// }
//}
/// <summary>
/// 加this 表示 IServiceCollection 的扩展方法
/// </summary>
/// <param name="services"></param>
public static void RegisterAssembly(this IServiceCollection services)
{
var list = MyGetTypes();
foreach (var type in list)
{
RegisterAssembly(services, type);
}
}
public static void RegisterAssembly(IServiceCollection services, Type type)
{
var list = GetExposedServices(type).ToList();
foreach (var item in list)
{
switch (item.Lifetime)
{
case Lifetime.Singleton:
services.AddSingleton(type);
break;
case Lifetime.Transient:
services.AddTransient(type);
break;
case Lifetime.Scoped:
services.AddScoped(type);
break;
default:
break;
}
foreach (var IType in item.Types)
{
switch (item.Lifetime)
{
case Lifetime.Singleton:
services.AddSingleton(IType, type);
break;
case Lifetime.Transient:
services.AddTransient(IType, type);
break;
case Lifetime.Scoped:
services.AddScoped(IType, type);
break;
default:
break;
}
}
}
}
在Ioc注册:
csharp
services.RegisterAssembly();
在View中使用:
csharp
using MyCode.BLL.Service.Ioc;
using System.Windows;
namespace MyCode.Views
{
/// <summary>
/// MainView.xaml 的交互逻辑
/// </summary>
[ExposedService(Lifetime.Singleton)]
public partial class MainView : Window
{
public MainView()
{
InitializeComponent();
}
}
}
成功结果: