Using C# Reflection to Call a Constructor

Using C# reflection to call a constructor

I don't think GetMethod will do it, no - but GetConstructor will.

using System;
using System.Reflection;

class Addition
{
public Addition(int a)
{
Console.WriteLine("Constructor called, a={0}", a);
}
}

class Test
{
static void Main()
{
Type type = typeof(Addition);
ConstructorInfo ctor = type.GetConstructor(new[] { typeof(int) });
object instance = ctor.Invoke(new object[] { 10 });
}
}

EDIT: Yes, Activator.CreateInstance will work too. Use GetConstructor if you want to have more control over things, find out the parameter names etc. Activator.CreateInstance is great if you just want to call the constructor though.

Reflection - Call constructor with parameters

Well, you can create your own Factory, and write a method, that checks constructors for the type and runs first parameterized ctor with its default values:

public static class MyFactory
{
public static T MyCreateInstance<T>()
where T : class
{
return (T) MyCreateInstance(typeof (T));
}

public static object MyCreateInstance(Type type)
{
var parametrizedCtor = type
.GetConstructors()
.FirstOrDefault(c => c.GetParameters().Length > 0);

return parametrizedCtor != null
? parametrizedCtor.Invoke
(parametrizedCtor.GetParameters()
.Select(p =>
p.HasDefaultValue? p.DefaultValue :
p.ParameterType.IsValueType && Nullable.GetUnderlyingType(p.ParameterType) == null
? Activator.CreateInstance(p.ParameterType)
: null
).ToArray()
)
: Activator.CreateInstance(type);
}
}

And then use this method:

var classType = loadedAssemblies
.Where(a => a != null && a.FullName.StartsWith("MY."))
.SelectMany(a => a.GetTypes())
.Distinct()
.ToArray()[0];

var curObject = MyFactory.MyCreateInstance(classType);

// This will return an array of values

object[] values = classType
.GetFields()
.Select(f => f.GetValue(curObject))
.ToArray();

P.S.
Here is a DotNet fiddle example.

Update:

The code is changed according to scenario you work with. Now we have two methods,
one returns object, and another one that can convert it to type T.

I've also updated the DotnetFiddle, please check it.

Reflectively call constructor which throws an exception

The FormatterServices.GetUninitializedObject method can create objects without invoke a constructor:

Return Type: System.Object

A zeroed object of the specified type.

https://msdn.microsoft.com/en-us/library/system.runtime.serialization.formatterservices.getuninitializedobject(v=vs.110).aspx

How to call constructor method with generic type not known at compile time

Ok, so I figured out the answer. Leaving it here for people that may need it in the future.

First we create the method that will use reflection:

 private ParentClass populateGenericParameter(ParentClass inputParameter, ExternalObject value) {
const string methodToInvoke = "initializeParameter";
ParentClass populatedParameter = null;
try {
MethodInfo method = typeof(this).GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
Type type = typeof(ChildClass<>).MakeGenericType(new Type[] {inputParameter.GetType()}).GetGenericArguments()[0].GetGenericArguments()[0];
if(type != null) {
MethodInfo genericMethod = method.MakeGenericMethod(type);
object[] methodArguments = new object[] {inputParameter, value};
populatedParameter = (ParentClass) genericMethod.Invoke(obj: this, parameters: methodArguments);
}
}
catch(Exception e) {
//logging here
}
return populatedParameter;
}

Then, we create the method that will be triggered by reflection:

private ChildClass<GenericType> initializeParameter<GenericType>(ChildClass<GenericType> inputParameter, ExternalObject value){
ChildClass<GenericType> populatedParameter = null;
if(inputParameter != null){
populatedParameter = new ChildClass<GenericType>(parameter.name, parameter.type, value, parameter.mappingFunction);
}
return populatedParameter
}

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

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

.Net Reflection: How to invoke a constructor that takes a interface as parameter

Creating a new class on the fly is never a straightforward task. You may, as @decyclone says, be able to use a mocking library to create one.

If you need more control over what the interface does than a mocking library gives, you may have to go down the route of code generation. There are classes in the System.Reflection.Emit namespace dedicated to creating code at runtime. But they're not for the faint of heart.

How to get the base constructor calling parameters with Reflection

At the reflection level, the only place this exists is in the method body of the constructor, which gets compiled as (HelloMessage):

.method public hidebysig specialname rtspecialname instance void
.ctor(string name) cil managed
{
.maxstack 8
L_0000: ldarg.0
L_0001: ldstr "Hello {0}"
L_0006: ldc.i4.1
L_0007: newarr string
L_000c: dup
L_000d: ldc.i4.0
L_000e: ldarg.1
L_000f: stelem.ref
L_0010: call instance void BaseMessage::.ctor(string, string[])
L_0015: ret
}

or (IntroductionMessage):

.method public hidebysig specialname rtspecialname instance void
.ctor(string name, string myName) cil managed
{
.maxstack 8
L_0000: ldarg.0
L_0001: ldstr "Hello {0}, I am {1}"
L_0006: ldc.i4.2
L_0007: newarr string
L_000c: dup
L_000d: ldc.i4.0
L_000e: ldarg.1
L_000f: stelem.ref
L_0010: dup
L_0011: ldc.i4.1
L_0012: ldarg.2
L_0013: stelem.ref
L_0014: call instance void BaseMessage::.ctor(string, string[])
L_0019: ret
}

So; via reflection you would have to get the method body (MethodInfo.GetMethodBody().GetILAsByteArray()) and manually deconstruct it (noting that you'll have compiled IL to deal with, not the text version I've shown). This is possible, but is massively over-complicated for what you probably want. There are runtime IL disassembly tools, but... again: massively overkill here.

I would recommend either:

  • just look at what values arrive in format in the BaseMessage at runtime
  • use a compile-time tool such as an analyzer - or parse the source with Roslyn - and get the data at build
  • something involving attributes or properties; it is pretty easy to get values from attributes or properties

Passing IConfiguration to constructor using Reflection

Solution:

the problem was in ILogger<Weekly> in Weekly class, I was trying to pass ILogger<dynamic> to ILogger<Weekly>

I just made a change in Weekly class :

public class Weekly 
{
public Guid SessionId { get; set; }
private readonly ILogger<dynamic> _logger;
private readonly IConfiguration _configuration;
public Weekly(ILogger<dynamic> ilogger, IConfiguration configuration)
{
_logger = ilogger;
_configuration = configuration;
SessionId = Guid.NewGuid();
Console.WriteLine("Weekly inestance created with id: " + SessionId.ToString());
_logger.LogInformation("Weekly inestance created with id: " + SessionId.ToString());
}
public void Report()
{
Console.WriteLine("Weekly report called");
_logger.LogInformation("Weekly report called");
}
}

and finally, it's working fine.



Related Topics



Leave a reply



Submit