Call the info method inherited from a private generic

private static void Main(string[] args) { var messageType = typeof (SampleHandler1); var genericType = typeof (IConsume<>).MakeGenericType(messageType); var genericArguments = genericType.GetGenericArguments(); var consumeMethod = genericType.GetMethod("Consume"); var constructorInfo = genericArguments[0].GetConstructor(Type.EmptyTypes); var classObject = constructorInfo.Invoke(new object[] {}); var argsx = new object[] {new SampleMessage {Name = "sample message"}}; consumeMethod.Invoke(classObject, argsx); } public interface IConsume<in T> where T : class { void Consume(T message); } public class SampleHandler1 : IConsume<SampleMessage> { public SampleHandler1() { Debugger.Break(); } public void Consume(SampleMessage message) { Debugger.Break(); Console.WriteLine("Message consume: " + message.Name); } } public interface IBaseMessage { } public class SampleMessage : IBaseMessage { public string Name { get; set; } } 

I tried looking here, but I cannot find a specific solution. As MSDN explains

OBJ Type: System.Object The object for which you want to call a method or constructor. If the method is static, this argument is ignored. If the constructor is static, this argument must be null or an instance of the class that defines the constructor.

classObject is an instance of the constructor, right? Why does this throw an exception: enter image description here

+4
source share
2 answers

This does not seem right. Analyze what happens here:

 var messageType = typeof (SampleHandler1); //simple enough, Type -> SampleHandler1 var genericType = typeof (IConsume<>).MakeGenericType(messageType); //so genericType is a Type -> IConsume<SampleHandler1> var genericArguments = genericType.GetGenericArguments(); //there only one, but Type[] { Type -> SampleHandler1 } var consumeMethod = genericType.GetMethod("Consume"); //MethodInfo -> IConsume<SampleHandler1>.Consume(SampleHandler1) var constructorInfo = genericArguments[0].GetConstructor(Type.EmptyTypes); //ConstructorInfo -> SampleHandler1..ctor() var classObject = constructorInfo.Invoke(new object[] {}); //new SampleHandler1() var argsx = new object[] {new SampleMessage {Name = "sample message"}}; //object[] { SampleMessage } consumeMethod.Invoke(classObject, argsx); //((IConsume<SampleHandler1>)classObject).Consume( SampleMessage ) -- oops? 

So classObject is SampleHandler1 , but you are trying to call IConsume<SampleHandler1>.Consume(SampleHandler1) and, even worse, give it SampleMessage as an argument.

I think you wanted to create SampleHandler1 and call IConsume<SampleMessage>.Consume(SampleMessage) on it:

 var messageType = typeof(SampleMessage); var genericType = typeof(IConsume<>).MakeGenericType(messageType); var consumeMethod = genericType.GetMethod("Consume"); var handlerType = typeof(SampleHandler1); var constructorInfo = handlerType.GetConstructor(Type.EmptyTypes); var classObject = constructorInfo.Invoke(new object[] {}); var argsx = new object[] {new SampleMessage {Name = "sample message"}}; consumeMethod.Invoke(classObject, argsx); 
+4
source

I'm not sure, but based on all the components that you have in your question, I suspect you're looking for something similar:

using System;

 public class Program { public static void Main() { var handlerType = typeof (SampleHandler1); var genericType = handlerType.GetInterface("IConsume`1"); var genericArguments = genericType.GetGenericArguments(); var consumeMethod = genericType.GetMethod("Consume"); var handlerConstructorInfo = handlerType.GetConstructor(Type.EmptyTypes); var handler = handlerConstructorInfo.Invoke(new object[] {}); var messageConstructorInfo = genericArguments[0].GetConstructor(Type.EmptyTypes); var messageObject = messageConstructorInfo.Invoke(new object[] {}); ((IBaseMessage)messageObject).Name = "Sample Message"; var argsx = new object[] {messageObject}; consumeMethod.Invoke(handler, argsx); } } public interface IConsume<in T> where T : class, IBaseMessage { void Consume(T message); } public class SampleHandler1 : IConsume<SampleMessage> { public SampleHandler1() { Console.WriteLine("SampleHandler1 constructed"); } public void Consume(SampleMessage message) { Console.WriteLine("Message consume: " + message.Name); } } public interface IBaseMessage { string Name { get; set; } } public class SampleMessage : IBaseMessage { public string Name { get; set; } } 

Here is a working Dotnetfiddle from the answer above: https://dotnetfiddle.net/YFmmzk

Console output:

SampleHandler1 built

Message Consumption: Message Example

It looks like you are confusing your handler and message types. You tried to pass an instance of the handler itself to the consumption method. Moreover, IBaseMessage was missing from the declaration of the Name property.

UPDATE

Below is a cleaned version of this answer:

 public class Program { public static void Main() { var handler = new DynamicConstructor(typeof (SampleHandler1)).New(); invokeIConsumeFor(handler, "Sample Message"); } private static void invokeIConsumeFor(object handler, string message) { var executer = new DynamicGenericInterfaceExecuter(handler, "IConsume`1"); var messageObject = executer.GetTypeArgumentConstructor(0, Type.EmptyTypes).New(); ((IBaseMessage) messageObject).Name = message; executer.Method("Consume", messageObject.GetType()).Call(messageObject); } } public class DynamicGenericInterfaceExecuter { private object instance; private Type genericInterfaceFromType; private Type[] genericTypeArguments; public DynamicGenericInterfaceExecuter(object instance, string interfaceName) { this.instance = instance; this.genericInterfaceFromType = instance.GetType().GetInterface(interfaceName); this.genericTypeArguments = this.genericInterfaceFromType.GetGenericArguments(); } public MethodExecuter Method(string methodName, params Type[] parameterTypes) { return new MethodExecuter(this.instance, this.genericInterfaceFromType, methodName, parameterTypes); } public DynamicConstructor GetTypeArgumentConstructor(int typeArgumentIndex, params Type[] constructorParameterTypes) { return new DynamicConstructor(this.genericTypeArguments[typeArgumentIndex], constructorParameterTypes); } } public class DynamicConstructor { private System.Reflection.ConstructorInfo constructor; public DynamicConstructor(Type type, params Type[] constructorParameters) { this.constructor = type.GetConstructor(constructorParameters); } public object New(params object[] constructorArguments) { return this.constructor.Invoke(constructorArguments); } } public class MethodExecuter { private object instance; private System.Reflection.MethodInfo method; public MethodExecuter(object instance, Type containerType, string methodName, Type[] methodParameters) { this.instance = instance; this.method = containerType.GetMethod(methodName, methodParameters); } public void Call(params object[] arguments) { this.Invoke(arguments); } public object Invoke(params object[] arguments) { return this.method.Invoke(instance, arguments); } } public interface IConsume<in T> where T : class, IBaseMessage { void Consume(T message); } public class SampleHandler1 : IConsume<SampleMessage> { public SampleHandler1() { Console.WriteLine("SampleHandler1 constructed"); } public void Consume(SampleMessage message) { Console.WriteLine("Message consume: " + message.Name); } } public interface IBaseMessage { string Name { get; set; } } public class SampleMessage : IBaseMessage { public string Name { get; set; } } 

And dotnetfiddle: https://dotnetfiddle.net/n9WHZ2

Keep in mind that this is not type-related in the least, but this does not seem to cause concern in your question.

0
source

All Articles