Joh*_*ohn 6 dependency-injection .net-core asp.net-core
我编写了一个自定义IServiceProviderFactory并将其安装在Program.cs一个新应用程序中,如下所示:
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseServiceProviderFactory(new PropertyInjectingContainerFactory())
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
Run Code Online (Sandbox Code Playgroud)
它确实会导致调用正确的配置函数Startup.cs:
public void ConfigureContainer(PropertyInjectingContainerFactory.Builder builder)
{
builder.AddInjectAttribute<InjectDependencyAttribute>();
}
Run Code Online (Sandbox Code Playgroud)
但是,我创建的容器仅解析两个服务:IConfiguration和IHost 。
其他所有内容显然都由默认容器解决(例如ILogger<T>控制器上的服务)。我做错了什么?
这是我的自定义工厂的代码 - 请理解我可能应该使用现有的第三方容器,但我也想了解这一切如何组合在一起。
public class PropertyInjectingContainerFactory : IServiceProviderFactory<PropertyInjectingContainerFactory.Builder>
{
public Builder CreateBuilder(IServiceCollection services)
{
return new Builder(services);
}
public IServiceProvider CreateServiceProvider(Builder containerBuilder)
{
return containerBuilder.CreateServiceProvider();
}
public class Builder
{
internal readonly IServiceCollection services;
internal List<Type> attributeTypes = new List<Type>();
public Builder(IServiceCollection services)
{
this.services = services;
}
public Builder AddInjectAttribute<A>()
where A : Attribute
{
attributeTypes.Add(typeof(A));
return this;
}
public IServiceProvider CreateServiceProvider()
=> new PropertyInjectingServiceProvider(services.BuildServiceProvider(), attributeTypes.ToArray());
}
class PropertyInjectingServiceProvider : IServiceProvider
{
private readonly IServiceProvider services;
private readonly Type[] injectAttributes;
public PropertyInjectingServiceProvider(IServiceProvider services, Type[] injectAttributes)
{
this.services = services;
this.injectAttributes = injectAttributes;
}
// This function is only called for `IConfiguration` and `IHost` - why?
public object GetService(Type serviceType)
{
var service = services.GetService(serviceType);
InjectProperties(service);
return service;
}
private void InjectProperties(Object target)
{
var type = target.GetType();
var candidateProperties = type.GetProperties(System.Reflection.BindingFlags.Public);
var props = from p in candidateProperties
where injectAttributes.Any(a => p.GetCustomAttributes(a, true).Any())
select p;
foreach (var prop in props)
{
prop.SetValue(target, services.GetService(prop.PropertyType));
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1836 次 |
| 最近记录: |