Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/264.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何使用标准MVC核心依赖项注入解析未注册的类型_C#_.net_Asp.net Mvc_Dependency Injection_Asp.net Core Mvc - Fatal编程技术网

C# 如何使用标准MVC核心依赖项注入解析未注册的类型

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未显式注册到容器中 没有 您可以创建自己的基于约定的注册(使用反射和

是否有一种方法可以让IServiceProvider.GetService返回一个实例,即使
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框架来创建一个配置类的实例。。。除了明显的核心'