& lt; T>找不到通过激活器创建的对象类型

本文关键字:激活 创建 类型 对象 lt 找不到 | 更新日期: 2023-09-27 18:07:00

我用下面的语法创建了一个对象:

var newMessage = Activator.CreateInstance(client.Key);

它似乎创建了一个正确类型的对象,并允许设置对象属性。但是,当我将对象传递给签名为:

的方法时
public void Publish<T>(T messageBody)

T定义的类型是object。

我如何绕过这个?我不能改变方法签名——它来自一个库——我需要能够在运行时创建对象,而不需要事先知道它们的类型。

我要执行的功能与发送(发布)消息有关。通常我会注册一个消息处理程序,如:

RegisterHandler<MyMessage> (m => do something with message );
然后可以调用
Publish<MyMessage> (message)

,它最终会在处理程序中结束。这很酷,效果很好。

我要做的是插入一个中介作为交换,并将消息发布到多个处理程序。我知道还有其他的东西可以用来为我做这件事,比如RabbitMQ,但我希望能够通过对当前代码的一个小修改来实现它。

我有一个注册订阅的方法:

 public virtual void registerSubscription<T1,T2>()
    {
        if (handlerMap.ContainsKey(typeof(T2)))
        {
            throw new ArgumentException("Message handler has already been registered for type: " +typeof(T2).Name);
        }
        if (!handlerMap.ContainsValue(typeof(T1)))
        {                              
            mqHost.RegisterHandler<T1> (m => distributeMessage(m) );
        }
        handlerMap[typeof(T2)] = typeof(T1);
    }

我用两个类调用方法,一个基类和继承基类的类:

public class MyMessage
{
    public string name {get;set;}
}
public class MyMessage2:MyMessage{}

这一点工作得很好,我得到了一个处理程序的映射。当我执行下一个位(distributeMessage方法)时,问题出现了。

var match = handlerMap.Where(i => i.Value == message.Body.GetType());
foreach (var client in match)
{
    var newMessage = Activator.CreateInstance(client.Key);
    newMessage.PopulateWith(message.Body);                
    messageProducer.Publish(createMessage(newMessage));                
}
messageProducer

。Publish具有签名:

public void Publish<T>(T messageBody)

我不能(很容易)修改它——它是库的一部分。我还可以调用另一个方法:

public void Publish<T>(IMessage<T> message)

但是我看不出这会更容易,因为我必须创建一个Message,这仍然需要。

& lt; T>找不到通过激活器创建的对象类型

根据调用Activator时知道的类型信息,可以使用一些反射来尝试创建Publish的泛型方法。如果我误解了你想要做的事情,请问我,我可以修改这个代码。

object newObject = Activator.CreateInstance(myType);
var publishMethod = typeof(MessageProducer).GetMethod("Publish");
var publishMethodWithCorrectType = publishMethod.MakeGenericMethod(new Type[] { myType });
publishMethodWithCorrectType.Invoke(messageProducer, new object[]{newObject});

试着这样做:

var newMessage = (MyType)Activator.CreateInstance(client.Key);

注。MyType是一个基类型或接口…

您还需要通过反射调用Publish<T>方法来继续这条路线。

另一个建议是使class对象的类基于client.Key类型的泛型,然后在该类中实现一个Publish方法-实现将知道T是什么。

找到了另一个问题的答案

并实现了这个:

 typeof(MessageExchange)
   .GetMethod("createMessage",BindingFlags.Static | BindingFlags.NonPublic)
   .MakeGenericMethod(newMessage.GetType())
   .Invoke(null, new object[] { newMessage });

我现在得到正确的类型被传递。