C# 如何使用标准MVC核心依赖项注入解析未注册的类型
是否有一种方法可以让IServiceProvider.GetService返回一个实例,即使C# 如何使用标准MVC核心依赖项注入解析未注册的类型,c#,.net,asp.net-mvc,dependency-injection,asp.net-core-mvc,C#,.net,Asp.net Mvc,Dependency Injection,Asp.net Core Mvc,是否有一种方法可以让IServiceProvider.GetService返回一个实例,即使T没有显式地注册到容器中 如果我知道T有依赖项,我希望根据它们的注册注入它们,而不必注册T本身 我相信Ninject会智能地计算出最合适的构造函数,或者在找不到合适的构造函数时退回到无参数构造函数。如果可能的话,我想使用标准的MVC核心DI框架复制这种行为 有没有办法让IServiceProvider.GetService返回实例,即使T未显式注册到容器中 没有 您可以创建自己的基于约定的注册(使用反射和
T
没有显式地注册到容器中
如果我知道T
有依赖项,我希望根据它们的注册注入它们,而不必注册T
本身
我相信Ninject会智能地计算出最合适的构造函数,或者在找不到合适的构造函数时退回到无参数构造函数。如果可能的话,我想使用标准的MVC核心DI框架复制这种行为
有没有办法让IServiceProvider.GetService返回实例,即使T未显式注册到容器中
没有
您可以创建自己的基于约定的注册(使用反射和扩展方法非常简单),或者使用第三方DI容器,该容器具有自己的基于约定的注册,但没有内置内容
另外,没有DI容器允许您在不首先注册实例的情况下创建实例,尽管其中一些容器会自动注册已知类型,如MVC控制器,而另一些容器会自动注册类型为“self”,以便您可以使用它们的具体类型自动解析它们 我相信Ninject会智能地计算出最合适的构造函数,或者在找不到合适的构造函数时退回到无参数构造函数。如果可能的话,我想使用标准MVC6DI框架复制这种行为
这确实与你的问题无关,尽管这是朝着错误方向迈出的又一步。请参阅。保持这一最新信息:有一种方法可以实现您想要的目标 标准的.NET内核依赖注入程序 在我的示例中,我为showcase创建了一个新的IServiceCollection实例:
var services = new ServiceCollection();
var serviceProvider = services.BuildServiceProvider();
var unregisteredClassInstance =
ActivatorUtilities.CreateInstance<UnregisteredClass>(serviceProvider);
var services=newservicecolection();
var serviceProvider=services.BuildServiceProvider();
var unregisteredClassInstance=
ActivatorUtilities.CreateInstance(serviceProvider);
这将为您提供一个类型UnregisteredClass的实例,该实例以前未注册,但采用了以前在ServiceCollection上注册的构造函数参数
第三方依赖关系注入程序
SimpleInjector可以使用
container.GetInstance()代码>虽然默认情况下无法解析未注册的具体类型,但您可以添加一个扩展函数,该函数将为您提供此功能。需要注意的是,这可能被滥用为服务定位器,这是一种反模式。根据您的使用情况,您可以利用此功能,而无需将其转换为服务定位器
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
namespace Microsoft.Extensions.DependencyInjection
{
public static class ServiceProviderExtensions
{
public static TService AsSelf<TService>(this IServiceProvider serviceProvider)
{
return (TService)AsSelf(serviceProvider, typeof(TService));
}
public static object AsSelf(this IServiceProvider serviceProvider, Type serviceType)
{
var constructors = serviceType.GetConstructors(BindingFlags.Public | BindingFlags.Instance)
.Select(o => o.GetParameters())
.ToArray()
.OrderByDescending(o => o.Length)
.ToArray();
if (!constructors.Any())
{
return null;
}
object[] arguments = ResolveParameters(serviceProvider, constructors);
if (arguments == null)
{
return null;
}
return Activator.CreateInstance(serviceType, arguments);
}
private static object[] ResolveParameters(IServiceProvider resolver, ParameterInfo[][] constructors)
{
foreach (ParameterInfo[] constructor in constructors)
{
bool hasNull = false;
object[] values = new object[constructor.Length];
for (int i = 0; i < constructor.Length; i++)
{
var value = resolver.GetService(constructor[i].ParameterType);
values[i] = value;
if (value == null)
{
hasNull = true;
break;
}
}
if (!hasNull)
{
// found a constructor we can create.
return values;
}
}
return null;
}
}
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
运用系统反思;
使用系统文本;
命名空间Microsoft.Extensions.DependencyInjection
{
公共静态类服务提供扩展
{
公共静态TService AsSelf(此IServiceProvider服务提供程序)
{
return(TService)AsSelf(serviceProvider,typeof(TService));
}
公共静态对象AsSelf(此IServiceProvider服务提供程序,类型为serviceType)
{
var constructors=serviceType.GetConstructors(BindingFlags.Public | BindingFlags.Instance)
.Select(o=>o.GetParameters())
.ToArray()
.OrderByDescending(o=>o.Length)
.ToArray();
if(!constructor.Any())
{
返回null;
}
对象[]参数=ResolveParameters(serviceProvider、构造函数);
if(参数==null)
{
返回null;
}
返回Activator.CreateInstance(serviceType,参数);
}
私有静态对象[]ResolveParameters(IServiceProvider解析器、ParameterInfo[]构造函数)
{
foreach(构造函数中的ParameterInfo[]构造函数)
{
bool hasNull=false;
object[]value=新对象[constructor.Length];
for(int i=0;i
@Rafal我已经为Clarity将问题更新为MVC6了我认为Ninject的Get
为未注册类型提供了“自我”行为?这就是我所说的第九段的意思。我可能会探索为IServiceProvider
创建GetServiceOrSelf
扩展的目的是什么?这意味着您正在将容器用作一个容器,而您不应该这样做。通过构造函数注入服务,不要注入IServiceProvider
。并构建一些基于约定的注册,以便于维护(或者使用具有基于约定注册的第三方容器)。但最终要提供容器注册,否则您将无法轻松更改注册或控制实例的生命周期,这就是DI的全部要点。对GetService
的调用在容器中,我不会传递IServiceProvider
的。我只是在寻找一种方便的方法来依靠DI框架来创建一个配置类的实例。。。除了明显的核心'