Message Topology

Message types are extensively leveraged in MassTransit, so making it easy to configure how those message types are used by topology seemed obvious.

Entity Name Formatters

Message Type

MassTransit has built-in defaults for naming messaging entities (these are things like exchanges, topics, etc.). The defaults can be overridden as well. For instance, to change the topic name used by a message, just do it!

Bus.Factory.CreateUsingRabbitMq(cfg =>
{
    cfg.Message<OrderSubmitted>(x =>
    {
        x.SetEntityName("omg-we-got-one");
    });
});

It's also possible to create a message-specific entity name formatter, by implementing IMessageEntityNameFormatter<T> and specifying it during configuration.

class FancyNameFormatter<T> :
    IMessageEntityNameFormatter<T>
{
    public string FormatEntityName()
    {
        // seriously, please don't do this, like, ever.
        return type(T).Name.ToString();
    }
}

Bus.Factory.CreateUsingRabbitMq(cfg =>
{
    cfg.Message<OrderSubmitted>(x =>
    {
        x.SetEntityNameFormatter(new FancyNameFormatter<OrderSubmitted>());
    });
});

It's also possible to replace the entity name formatter for the entire topology.

class FancyNameFormatter<T> :
    IMessageEntityNameFormatter<T>
{
    public string FormatEntityName()
    {
        // seriously, please don't do this, like, ever.
        return type(T).Name.ToString();
    }
}

class FancyNameFormatter :
    IEntityNameFormatter
{
    public FancyNameFormatter(IEntityNameFormatter original)
    {
        _original = original;
    }

    public string FormatEntityName<T>()
    {
        if(T is OrderSubmitted)
            return "we-got-one";

        return _original.FormatEntityName<T>();
    }
}

Bus.Factory.CreateUsingRabbitMq(cfg =>
{
    cfg.Message<OrderSubmitted>(x =>
    {
        x.SetEntityNameFormatter(new FancyNameFormatter(cfg.MessageTopology.EntityNameFormatter));;
    });
});

Attributes

EntityName

EntityName is an optional attribute used to override the default entity name for a message type. If present, the entity name will be used when creating the topic or exchange for the message.

[EntityName("order-submitted")]
public record LegacyOrderSubmittedEvent
{
}

ConfigureConsumeTopology

ConfigureConsumeTopology is an optional attribute that may be specified on a message type to indicate whether the topic or exchange for the message type should be created and subscribed to the queue when consumed on a receive endpoint.

[ConfigureConsumeTopology(false)]
public record DeleteRecord
{
}

ExcludeFromTopology

ExcludeFromTopology is an optional attribute that may be specified on a message type to indicate whether the topic or exchange for the message type should be created when publishing an implementing type or sub-type. In the example below, publishing the ReformatHardDrive command would not create the ICommand topic or exchange on the message broker.

[ExcludeFromTopology]
public interface ICommand
{
}

public record ReformatHardDrive :
    ICommand
{
}

As an alternative to using the ExcludeFromTopology attribute, configure the publish topology during bus configuration.

x.UsingRabbitMq((context,cfg) =>
{
    cfg.Publish<ICommand>(p => p.Exclude = true);
});

ExcludeFromImplementedTypes

ExcludeFromImplementedTypes is an optional attribute that may be specified on a base message type to prevent scope filters being created for the message type.

[ExcludeFromImplementedTypes]
public interface ICommand
{
}

public record ReformatHardDrive :
    ICommand
{
}