简体   繁体   中英

call c# class method by reflection with constructor using dependency injection

 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();

I call the class method, which implements IProviderProcessor interface using reflection. if I declare a constructor in Class1 class and add interfaces using DI, I get this error:

System.MissingMethodException: No parameterless constructor defined for type 'UtilityPayments.Providers.TestProvider.Class1'. at System.RuntimeType.CreateInstanceDefaultCtorSlow(Boolean publicOnly, Boolean wrapExceptions, Boolean fillCache) at System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, Boolean wrapExceptions)
at System.Activator.CreateInstance(Type type, Boolean nonPublic, Boolean wrapExceptions)

Class1 constructor:

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

How can I call Class1 methods using reflection if I want to inject interfaces in the constructor? The code works fine if I remove the constructor, but I need to use applications other functionalities in Class1 , which are implemented using dependency injection.

I had to solve this near exact problem. What i found to be the easiest, maybe not the best, was to use a ServiceProvider.

in whatever class you want to run your code add a ServiceProvider:

private protected IServiceProvider _serviceProvider;

You can inject it as normal:

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

then replace:

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

with:

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

thank you for your help.I solved it using serviceprovider to get instance of the interfaces which are injected in constructor of the Class1 class.

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();

Activator.CreateInstance has a prototype that allows you to pass constructor arguments. They need to be contained, in order, within an array of objects, as shown below.

Of course, you'll need to be able to get a reference to a provider service somehow.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM