[C#]在Microsoft.Extensions.DependencyInjection中使用属性注入
背景
- 有一些特殊需求,需要像StringBoot那样使用属性注入。(不推荐使用属性注入)
实现
- 设计一个属性注入注解:
InjectAttribute
[AttributeUsage(AttributeTargets.Property)]
public class InjectAttribute : Attribute
{
}
- 设计属性注入服务接口:
IResolvedService
public interface IResolvedService<TService> where TService : class
{
TService Service { get; }
}
- 实现属性注入服务
internal class ServiceResolver<TService> : IResolvedService<TService> where TService : class
{
private static readonly ConcurrentDictionary<Type, PropertyInfo[]> _propertyCache = new();
public ServiceResolver(IServiceProvider serviceProvider)
{
Service = ResolveService(serviceProvider);
}
public TService Service { get; }
private static void InjectProperties(IServiceProvider services, object instance)
{
ArgumentNullException.ThrowIfNull(instance);
var properties = _propertyCache.GetOrAdd(instance.GetType(), type =>
type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
.Where(prop => prop.CanWrite && Attribute.IsDefined(prop, typeof(InjectAttribute)))
.ToArray());
foreach (var property in properties)
{
var dependency = services.GetService(property.PropertyType)
?? throw new InvalidOperationException($"Failed to resolve dependency for property '{property.Name}' of type '{property.PropertyType.FullName}'.");
property.SetValue(instance, dependency);
}
}
private static TService ResolveService(IServiceProvider services)
{
var service = services.GetService(typeof(TService));
if (service is not TService typedService)
{
throw new InvalidOperationException($"Unable to resolve service of type '{typeof(TService).FullName}'.");
}
InjectProperties(services, typedService);
return typedService;
}
}
- 在DI中注册服务
services.AddTransit(typeof(IResolvedService<>),typeof(ResolvedService<>));
- 定义属性注入
public class ExampleService
{
[Inject]
DependencyService Dependency { get; set; }
}
- 使用服务
- 使用构造注入
public class SomeViewModel
{
private readonly ExampleService _exampleService;
public SomeViewModel(IResolvedService<ExampleService> exampleService)
{
_exampleService = exampleService.Service;
}
}
- 使用ServiceProvider获取服务
IResolvedService resolver = serviceProvider.GetRequiredService<IResolvedService<ExampleService>();
ExampleService service = resolver.Service;
最后
spring官方也不推荐属性注入,微软没有支持这个也是正常的。这里给有需要的兄弟提供一下思路。

浙公网安备 33010602011771号