Home > Software engineering >  NService bus 'Publish()' base interface not sending concrete child class properties
NService bus 'Publish()' base interface not sending concrete child class properties

Time:04-12

I am using an interface to send message to a handler using NServicebus. Below is the interface:

interface IDeliveryTarget
{
        public DeliveryType DeliveryType { get; }
        public string DocumentId { get; set; }
}

Child Classes Email and Fax:

class EmailTarget : IDeliveryTarget
{
    public DeliveryType DeliveryType => DeliveryType.Email;
    public int DocumentId {get;set;}
    public string MessageBody { get; set; }
    public string[] Recepients { get; set; }
    public string Subject { get; set; }
}
class FaxTarget : IDeliveryTarget
{
    public DeliveryType DeliveryType => DeliveryType.Email;
    public int DocumentId {get;set;}
    public string FaxNumber { get; set; }
    public string FaxUserName { get; set; }
    public string Organization { get; set; }
    public string Subject { get; set; }
}

I send List<IDeliveryTarget> from handler as below:

context.Publish(new UploadSuccess
{
   DeliveryTargets = new List<IDeliveryTarget>()
} 

This list has many Email and Fax inputs.

Handled in another Saga as below:

public async Task Handle(UploadSuccess message, IMessageHandlerContext context)

But here the UploadSuccess message has only properties defined in IDeliveryTarget interface but Email and Fax specific properties are missing.

I except Email and Fax properties to be present for further processing. Please guide.

CodePudding user response:

An alternative solution to what @MindSwipe mentioned is to have dedicated properties on the event for each of the concrete types ie.:

context.Publish(new UploadSuccess
{
   EmailTargets = new List<EmailTarget>(),
   FaxTargest = new List<FaxTarget>();
} 

This will allow you to access concrete types' properties in a handler without the need for casting.

CodePudding user response:

You need to cast the items in DeliveryTarget to a concrete implementation of your interface, those properties are still there, they're just hidden to intellisense because you have a variable of type IDeliveryTarget which doesn't declare those properties you want.

Do something like this:

public async Task Handle(UploadSuccess message, IMessageHandlerContext ctx)
{
    foreach (IDeliveryTarget target in message.DeliveryTargets)
    {
        if (target is EmailTarget emailTarget)
        {
            Console.WriteLine($"Got email target with subject {emailTarget.Subject}");
        }
        else if ( ... )
    }
}

This becomes cumbersome with lots of implementations, I'd suggest you add a method like Handle to the IDeliveryTarget interface and use polymorphism to shorten that to:

public async Task Handle(UploadSuccess message, IMessageHandlerContext ctx)
{
    foreach (IDeliveryTarget target in message.DeliveryTargets)
        await target.Handle();
}
  • Related