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; }
}
我试过看这里,但我找不到具体的解决方案。正如MSDN解释
OBJ 键入:System.Object 要调用方法或构造函数的对象。如果方法是静态的,则忽略此参数。如果构造函数是静态的,则此参数必须为null或定义构造函数的类的实例。
答案 0 :(得分:4)
这似乎不对。让我们分析一下这里发生了什么:
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's 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?
所以classObject
是SampleHandler1
,但您正在尝试调用IConsume<SampleHandler1>.Consume(SampleHandler1)
,更糟糕的是,它会以SampleMessage
作为参数。
我认为您打算创建一个SampleHandler1
,并在其上调用IConsume<SampleMessage>.Consume(SampleMessage)
:
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);
答案 1 :(得分:0)
我不确定,但根据你问题中的所有组件,我怀疑你正在寻找更像这样的东西:
使用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; }
}
这是上述答案的一个有效的Dotnetfiddle:https://dotnetfiddle.net/YFmmzk
控制台输出是:
构建SampleHandler1
消息使用:示例消息
看起来你的处理程序和消息类型混淆了。您试图将处理程序本身的实例传递给consume方法。更重要的是,IBaseMessage缺少Name
属性声明。
<强>更新强>
以下是此答案的cleaned版本:
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; }
}
dotnetfiddle:https://dotnetfiddle.net/n9WHZ2
请记住,这不是最安全的类型,但在您的问题中似乎不是一个问题。