.NET Core 依赖注入改造(4)- ActivatorUt
.NET Core 依赖注入改造(1)- 命名服务
.NET Core 依赖注入改造(2)- 委托转换
.NET Core 依赖注入改造(3)- ILogger
.NET Core 依赖注入改造(4)- ActivatorUtilities
.NET Core 依赖注入改造(5)- Context
.NET Core 依赖注入改造(附1)- Autowrite
一、
ActivatorUtilitiesActivatorUtilities 看注释就知道这是一个用于创建对象的帮助类
使用起来也很简单
CreateInstance但是缺少了类似Java中的Autowrite
功能
今天就改造这个
二、
先假想一个完成后的样子
static void Main(string[] args)
{
var provider = new ServiceCollection()
.AddLogging()
.BuildServiceProvider();
var a = new MyClass();
provider.Autowrite(a);
}
class MyClass
{
[Autowrite]
private ILogger<MyClass> Logger { get; }
}
从上面这个代码中可以看出,需要先定义个AutowriteAttribute
然后实现一个扩展方法Autowrite(this IServiceProvider serviceProvider, object instance)
三、
AutowriteAttribute
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, Inherited = false, AllowMultiple = false)]
public sealed class AutowriteAttribute : Attribute, IServiceProviderFactory<IServiceProvider>
{
public IServiceProvider CreateBuilder(IServiceCollection services) => throw new NotImplementedException();
public IServiceProvider CreateServiceProvider(IServiceProvider containerBuilder) => containerBuilder;
}
这里实现了接口 IServiceProviderFactory<IServiceProvider>
是为了更好的扩展性
看完扩展方法后就会明白
public static IServiceProvider Autowrite(this IServiceProvider serviceProvider, object instance)
{
if (serviceProvider == null || instance == null)
{
return serviceProvider;
}
var flags = BindingFlags.Public | BindingFlags.NonPublic;
var type = instance as Type ?? instance.GetType();
if (instance is Type)
{
instance = null;
flags |= BindingFlags.Static;
}
else
{
flags |= BindingFlags.Instance;
}
// 字段
foreach (var field in type.GetFields(flags))
{
var attr = field.GetCustomAttributes().OfType<IServiceProviderFactory<IServiceProvider>>().LastOrDefault();
var value = attr?.CreateServiceProvider(serviceProvider).GetServiceOrCreateInstance(field.FieldType);
if (value != null)
{
field.SetValue(instance, value);
}
}
foreach (var property in type.GetProperties(flags))
{
var attr = property.GetCustomAttributes().OfType<IServiceProviderFactory<IServiceProvider>>().LastOrDefault();
var value = attr?.CreateServiceProvider(serviceProvider).GetServiceOrCreateInstance(property.PropertyType);
if (value != null)
{
var setter = property.GetSetMethod(true);
if (setter != null)
{ // 一般属性
setter.Invoke(instance, new[] { value });
}
else if (type.GetField($"<{property.Name}>k__BackingField", flags) is FieldInfo field)
{ // 只读属性
field.SetValue(instance, value);
}
}
}
return serviceProvider;
}
仔细看这一行
GetCustomAttributes().OfType<IServiceProviderFactory<IServiceProvider>>().LastOrDefault()
可以看出在这里获取特性Attribute时,没有指定AutowriteAttribute
类型,而是获取所有特性后筛选出实现 IServiceProviderFactory<IServiceProvider>
接口的特性,进行下一步操作,所以这里方便随时扩展功能,重新实现一个特性代替AutowriteAttribute
,进行部分行为干涉。
顺便多做了一个 GetServiceOrCreateInstance
扩展方法,等于
ActivatorUtilities.GetServiceOrCreateInstance
+Autowrite
public static object GetServiceOrCreateInstance(this IServiceProvider serviceProvider, Type type)
{
if (serviceProvider == null)
{
return Activator.CreateInstance(type);
}
var obj = ActivatorUtilities.GetServiceOrCreateInstance(serviceProvider, type);
if (obj != null)
{
serviceProvider.Autowrite(obj);
}
return obj;
}
用于方便获取服务值时进行递归操作
var value = attr?.CreateServiceProvider(serviceProvider).GetServiceOrCreateInstance(property.PropertyType);
if (value != null)
{
field.SetValue(instance, value);
}
四、
最终效果ps: 也可以通过
Type
实例来注入静态属性或字段
static void Main(string[] args)
{
var provider = new ServiceCollection()
.AddLogging()
.BuildServiceProvider();
provider.Autowrite(typeof(MyClass));
}
class MyClass
{
[Autowrite]
public static ILogger<MyClass> Logger { get; }
[Autowrite]
private readonly static ILogger<MyClass> _logger;
}
五、
最后把ActivatorUtilities
中的所有静态方法都扩展一遍
public static object GetServiceOrCreateInstance(this IServiceProvider serviceProvider, Type type)
{
if (serviceProvider == null)
{
return Activator.CreateInstance(type);
}
var obj = ActivatorUtilities.GetServiceOrCreateInstance(serviceProvider, type);
if (obj != null)
{
serviceProvider.Autowrite(obj);
}
return obj;
}
public static ObjectFactory CreateFactory(this IServiceProvider serviceProvider, Type instanceType, Type[] argumentTypes)
{
var factory = ActivatorUtilities.CreateFactory(instanceType, argumentTypes);
if (factory == null)
{
return factory;
}
return (provider, args) =>
{
var obj = factory(provider, args);
if (obj != null)
{
provider?.Autowrite(obj);
}
return obj;
};
}
public static object CreateInstance(this IServiceProvider provider, Type instanceType, params object[] parameters)
{
var obj = ActivatorUtilities.CreateInstance(provider, instanceType, parameters);
if (obj != null)
{
provider.Autowrite(obj);
}
return obj;
}
public static T CreateInstance<T>(this IServiceProvider provider, params object[] parameters) =>
(T)CreateInstance(provider, typeof(T), parameters);
public static T GetServiceOrCreateInstance<T>(this IServiceProvider provider) =>
(T)GetServiceOrCreateInstance(provider, typeof(T));
六、
github:https://github.com/blqw/blqw.DI/tree/master/src/blqw.DI.ExtensionMethods
nuget:https://www.nuget.org/packages/blqw.DI.ExtensionMethods