Не удается получить доступ к значению типа интерфейса в очереди azure служебной шины с помощью masstransit - PullRequest
3 голосов
/ 10 января 2020

Я отправляю сообщение в azure очередь служебной шины с помощью masstransit, где интерфейс модели сообщений имеет внутри себя другой интерфейс. Моя схема сообщения выглядит следующим образом:

public interface IMyMessage
{
    Guid NormalProp1 { get; set; }

    IVariableProp VariableProp { get; set; }
}

public interface IVariableProp
{

}

Здесь IvariableProp - это интерфейс, потому что я хочу отправлять в него переменные типы данных. Как:

public class VarietyProp1 : IVariableProp
{
    public Guid VarietyGuid1 { get; set; }
}

public class YetAnotherVarietyProp : IVariableProp
{
    public Guid YetAnotherVarietyGuid { get; set; }
    public bool YetAnotherVarietyBool { get; set; }
}

И в конце мое конкретное сообщение:

public class MyConcreteMessage : IMyMessage
{
    public Guid NormalProp1 { get; set; }

    public IVariableProp VariableProp { get; set; }
}

Я отправил экземпляр моего конкретного сообщения в azure очередь служебной шины. Конкретное сообщение выглядит следующим образом:

    var variety1 = new MyConcreteMessage()
                       {
                           NormalProp1 = Guid.NewGuid(),
                           VariableProp = new VarietyProp1()
                                              {
                                                  VarietyGuid1 = Guid.NewGuid()
                                              }
                       };

Это сообщение отправляется на служебную шину azure без проблем, и все значения отправляются правильно. (Я проверил с помощью azure Service Bus Explorer).

Проблема возникает, когда я пытаюсь использовать сообщение с функцией azure с помощью masstransit. Здесь В моем коде Iconsumer значение VariableProp равно нулю. Мой код функции azure приведен ниже:

        using (var dependencyScope = Program.AppDependencyResolver.BeginScope())
        {

            var scopedDependencyResolver = dependencyScope.Resolve<IDependencyResolver>();
            IOperationContext operationContext = dependencyScope.Resolve<OperationContext>();
            var serviceTriggerConfiguration = dependencyScope.Resolve<IServiceBusConsumerConfig>();


            var logger = dependencyScope.Resolve<ILogger>();

            logger.Info(() => $"ConsumeEventsFromQueue function is triggered");
            string convertedMessage = Encoding.UTF8.GetString(message.Body, 0, message.Body.Length);
            var retryCount = serviceTriggerConfiguration.RetryCount;
            var interval = serviceTriggerConfiguration.IntervalInMilliSeconds;
            var receiver = Bus.Factory.CreateBrokeredMessageReceiver(
                binder,
                cfg =>
                {
                    cfg.CancellationToken = cancellationToken;
                    cfg.SetLog(traceWriter);
                    cfg.UseRetry(x => x.Interval(retryCount, interval));
                    cfg.Consumer(() => scopedDependencyResolver.Resolve<EventConsumer>());

                });
            await receiver.Handle(message);

, а мой код потребителя:

public class EventConsumer:IConsumer<IMyMessage>
{
    public async Task Consume(ConsumeContext<IMyMessage> context)
    {
        var message = context.Message;
    }
}

В коде потребителя я не могу получить значение VariableProp . Когда я устанавливаю указатель отладки, он показывает что-то вроде ниже:

Here message type is GreenPipes.DynamicInternal.Events.IVariableProp

Но когда я устанавливаю указатель отладки в своей функции и преобразую массив байтов тела в строка, я мог видеть значение VariableProp .

Value of variableProp is available here

Я подозреваю, что значение теряется / инкапсулируется, когда Потребитель вызывается через код:

cfg.Consumer(() => scopedDependencyResolver.Resolve<EventConsumer>());

Я хочу получить доступ к значению VariableProp от потребителя. Что я могу сделать?

1 Ответ

1 голос
/ 10 января 2020

Это не проблема MassTransit, а проблема сериализации. Когда вы десериализуете IMyMessage, он десериализует IVariableProp как IVariableProp, то есть интерфейс без свойств. Это связано с тем, что из определения интерфейса невозможно определить, какой конкретный тип должен скрываться за IVariableProp.

. Вот достойное сообщение в блоге, подробно описывающее проблему и решение: http://appetere.com/post/serializing-interfaces-with-jsonnet.

Мое личное предложение - не делать этого. Сделайте свои контракты на сообщения максимально простыми и очевидными. Я даже не уверен, что вышеуказанное решение будет работать с MassTransit. Если вы хотите пойти по пути безумия и продолжить этот подход, я предложу один совет: возможно настроить параметры сериализатора MassTransit JSON с помощью синглтона JsonMessageSerializer.SerializerSettings.

...