通过使用依赖项注入的构造函数进行反射来调用c#类方法

问题描述

 var fileName = string.Format(@"{0}\{1}\{2}.dll",Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location)),"ProviderDLLS",$"UtilityPayments.Providers.TestProvider");
 if (!File.Exists(fileName)) return null;
 AssemblyName an = AssemblyName.GetAssemblyName(fileName);
 Assembly assembly = Assembly.LoadFile(fileName);
 Type objectType = assembly.GetType("UtilityPayments.Providers.TestProvider.Class1");
 IProviderProcessor remoteAssembly = (IProviderProcessor)Activator.CreateInstance(objectType);
 return await remoteAssembly.GetProviderData();

我调用类方法,该方法使用反射实现IProviderProcessor接口。 如果我在Class1类中声明构造函数,并使用DI添加接口,则会收到此错误:

System.MissingMethodException:未定义无参数构造函数 对于类型'UtilityPayments.Providers.TestProvider.Class1'。在 System.RuntimeType.CreateInstanceDefaultCtorSlow(布尔publicOnly, 布尔wrapExceptions,布尔fillCache) System.RuntimeType.CreateInstanceDefaultCtor(布尔publicOnly, 布尔skipCheckThis,布尔fillCache,布尔wrapExceptions)
在System.Activator.CreateInstance(Type type,Boolean nonPublic, 布尔wrapExceptions)

Class1构造函数:

public class Class1: IProviderProcessor
{
    private readonly IProviderService _providerService;
    
    public Class1(IProviderService providerService)
    {
        _providerService = providerService;
    }
    
}

如果要在构造函数中注入接口,如何使用反射调用Class1方法? 如果删除构造函数,代码可以正常工作,但是我需要在应用程序中使用Class1中的其他功能,这些功能是通过依赖项注入实现的。

解决方法

Activator.CreateInstance有一个原型,允许您传递构造函数参数。它们必须按顺序包含在对象数组中,如下所示。

当然,您需要能够以某种方式获得对提供者服务的引用。

var providerService = GetProviderServiceFromSomewhere();
var arguments = new object[] { providerService };
IProviderProcessor remoteAssembly = (IProviderProcessor)Activator.CreateInstance(objectType,arguments);
,

我不得不解决这个几乎确切的问题。 我发现最简单(也许不是最好)的是使用ServiceProvider。

在要运行代码的任何类中添加ServiceProvider:

private protected IServiceProvider _serviceProvider;

您可以正常注入它:

public YourClass(IServiceProvider services){_serviceProvider = services;}

然后替换:

IProviderProcessor remoteAssembly = (IProviderProcessor)Activator.CreateInstance(objectType);

具有:

IProviderProcessor remoteAssembly = (IProviderProcessor)_serviceProvider.GetRequiredService(objectType);

,

谢谢您的帮助。我使用serviceprovider解决了它,并获得了注入到Class1类的构造函数中的接口的实例。

var fileName = string.Format(@"{0}\{1}\{2}.dll",Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location)),"ProviderDLLS",$"UtilityPayments.Providers.TestProvider");
if (!File.Exists(fileName)) return null;
AssemblyName an = AssemblyName.GetAssemblyName(fileName);
Assembly assembly = Assembly.LoadFile(fileName);
Type objectType = assembly.GetType("UtilityPayments.Providers.TestProvider.Class1");
var constructors = objectType.GetConstructors();
var firstConstrutor = constructors.FirstOrDefault(); //assume we will have only one constructor
var parameters = new List<object>();

foreach (var param in firstConstrutor.GetParameters())
{
   var service = _serviceProvider.GetService(param.ParameterType);//get instance of the class
   parameters.Add(service);
}

IProviderProcessor remoteAssembly = (IProviderProcessor)Activator.CreateInstance(objectType,parameters.ToArray());
return await remoteAssembly.GetProviderData();

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...