0

I'm trying to deserialize objects using generics but consumers can't pick them up even though they look completely fine.

    private readonly IContainer _container = Ioc.GetContainer();

    public async Task Test()
    {
        var command = new TestCommand();

        var serializeObject = JsonConvert.SerializeObject(command);

        var message = JsonConvert.DeserializeObject(serializeObject, command.GetType());

        await Process(message);

        await Process(command);
    }

    private async Task Process<TMessage>(TMessage message)
    {
        await _container.Resolve<IMessageDispatcher>().Dispatch(message);
    }

    public async Task Dispatch<TMessage>(TMessage message)
    {
        using (var scope = _lifetimeScope.BeginLifetimeScope())
        {
            var consumers = scope.Resolve<IEnumerable<IMessageConsumer<TMessage>>>().ToList();

            if(consumers.Any() == false) throw new Exception($"No consumer for message {message.GetType().Name}");

            foreach (var consumer in consumers)
            {
                await consumer.Consume(message, CancellationToken.None);
            }
        }
    }

    public interface IMessageConsumer<TMessage>
    {
      Task Consume(TMessage message, CancellationToken cancellationToken);
    }

My message fails to find a consumer but the command variable does? Even though these objects look identical?

1
  • 3
    There is much code there that complicates things including the use of an IoC container. Please simplify this down to a minimal reproducible example. Commented Apr 8, 2020 at 7:39

1 Answer 1

1

The variable message below will be of compile time type object and runtime type TMessage. For generics type binding to work, the type needs to be possible to evaluate at compile time.

var message = JsonConvert.DeserializeObject(serializeObject, command.GetType());

You will either need to Deserialize to a more specific generic type:

var message = JsonConvert.DeserializeObject<TestCommand>(serializeObject);

or check the type at runtime in some way, for example:

if(message is TestCommand)

... 
Sign up to request clarification or add additional context in comments.

2 Comments

This is what I thought but was hoping to avoid with having around 30 messages
There seems to be ways to deal with your problem (to dynamically create a MessageDispatcher with a generic type parameter for your command type): stackoverflow.com/a/53250059/1257728 Not sure what dependency injection you are using, but I think that it might be possible to rewrite the example in the link to fit your scenario

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.