1

我对消息传递相当陌生,我决定使用 EasyNetQ (RabbitMQ .Net) 构建一个原型。

我已经创建了发布者和订阅者,一切似乎都运行良好。我的 Web 服务应用程序中有 Publisher 捕获所有发送到数据库的命令。我让控制台应用程序中的订阅者接收消息。

但是,当订阅者获取 Command 对象时,它会抛出错误:

一个类应该有一个默认构造函数、一个带参数的构造函数或一个标有 JsonConstructor 属性的构造函数。

在我的原型中,我有一个像这样的 Command 类:

[Serializable]
public class Command
{
    private Type _type;
    private string _method;
    private object[] _params;

    public Command(){
    }

    public Command(Type type, string method, params object[] Params)
    {
        _type       = type;
        _method     = method;
        _params     = Params;
    }

    public Command(Type type, string method, params object[] Params)
    {
        _type           = type;
        _method         = method;
        _params         = Params;
    }

    public Type Type { get { return _type; } }
    public string Method { get { return _method; } }


    public object[] Params { get { return _params; } }
}

我将此命令对象传递给发布者:

public void Publish(Command message){
        using(var publishChannel = RabbitManager.Instance.OpenPublishChannel()){
            publishChannel.Publish(message);
        }
    }

订阅者拿起消息:

public void SubscribeCommand(){
        RabbitManager.Instance.Subscribe<Command>("my_subscription_id", msg => Console.WriteLine(msg.Method));
    }

当我运行它并且订阅者处理命令对象时,我收到错误:

错误:订阅回调引发的异常。

Exchange: 'Entities_Command:BL'
Routing Key: ''
Redelivered: 'False'

Message: {"Type":"BL.DataAccess.XXX, BL, Version=1.2.0.0, Culture=neutral, PublicKeyToken=xxx","Method ":"GET","Params":[1,true,3]}

基本属性:

ContentType=NULL, ContentEncoding=NULL, Headers=[], DeliveryMode=2, Priority=0, CorrelationId=8aa21f39-4020-4904-b90d-4cb123d3cac0, ReplyTo=NULL, Expiration=NULL, MessageId=NULL, Timestamp=0,Type =Entities_Command:BL,UserId=NULL,AppId=NULL,ClusterId=NULL 异常:Newtonsoft.Json.JsonSerializationException:找不到用于类型 Entities.Command 的构造函数。一个类应该有一个默认构造函数、一个带参数的构造函数或一个标有 JsonConstructor 属性的构造函数。路径“类型”,第 1 行,位置 8。Newtonsoft.Json.SerializerInternalReader.CreateNewObject(JsonReader 阅读器,JsonObjectContract objectContract,JsonProperty containerMember,JsonProperty containerProperty,String id,Boolean& createdFromNonDefaultConstructor)在 Newtonsoft.Json.Serialization。DisplayClass5`1.b _4(Byte[] body, MessageProperties properties, MessageReceivedInfo messageRecievedInfo) 在 EasyNetQ.Consumer.HandlerRunner.InvokeUserMessageHandler(ConsumerExecution Context context)

我在 Command 类中有一个默认构造函数,但我仍然不确定为什么会这样。

我试过只通过一个对象类型(而不是命令),它工作正常。

有人可以解释我在这里做错了什么吗?

4

1 回答 1

1

EasyNetQ 在内部使用 Newtonsoft.JSON 序列化程序。它期望消息类型是具有默认构造函数(即没有构造函数,或没有参数)和读写属性的简单 DTO。您的消息类型 Command 类具有只读属性,这就是序列化失败的原因。

序列化程序的另一个限制是它不处理多态类型。如果您希望能够将您的 object[] 参数转换为可用的东西,那么它不会起作用。

命令模式不是 EasyNetQ当前设计支持的一种,尽管值得考虑使用高级 API 并进行自己的自定义序列化。不过,计划是在不久的将来发布一个支持多态命令的版本。

于 2013-10-22T14:33:45.113 回答