Getting Started
Architecture
Transports
Persistence
ServiceInsight
ServicePulse
ServiceControl
Monitoring
Samples

Conventions

Component: NServiceBus
NuGet Package: NServiceBus (9.1)

Conventions can be used to identify which types are messages, commands, and events, instead of using marker interfaces. This can be done to avoid references to the NServiceBus assembly, referred to as unobtrusive mode. This is ideal for use in cross-platform environments.

Currently conventions exist to identify:

Message types can be defined in a Portable Class Library (PCL) and shared across multiple platforms, even if the platform does not use NServiceBus for message processing.

var conventions = endpointConfiguration.Conventions();
conventions.DefiningCommandsAs(type => type.Namespace == "MyNamespace.Messages.Commands");
conventions.DefiningEventsAs(type => type.Namespace == "MyNamespace.Messages.Events");
conventions.DefiningMessagesAs(type => type.Namespace == "MyNamespace.Messages");
conventions.DefiningDataBusPropertiesAs(property => property.Name.EndsWith("DataBus"));
conventions.DefiningTimeToBeReceivedAs(type => type.Name.EndsWith("Expires") ? TimeSpan.FromSeconds(30) : TimeSpan.MaxValue);

Using both default and custom conventions

Defining a custom convention will overwrite the default convention. If both default and custom conventions are needed, the default conventions must be specified along with the custom conventions.

var conventions = endpointConfiguration.Conventions();
conventions.DefiningCommandsAs(type =>
    type.Namespace == "MyNamespace.Messages.Commands"
    || typeof(ICommand).IsAssignableFrom(type)
);
conventions.DefiningEventsAs(type =>
    type.Namespace == "MyNamespace.Messages.Events"
    || typeof(IEvent).IsAssignableFrom(type)
);
conventions.DefiningMessagesAs(type =>
    type.Namespace == "MyNamespace.Messages"
    || typeof(IMessage).IsAssignableFrom(type)
);
conventions.DefiningDataBusPropertiesAs(property =>
    property.Name.EndsWith("DataBus")
    || typeof(IDataBusProperty).IsAssignableFrom(property.PropertyType) && typeof(IDataBusProperty) != property.PropertyType
);
conventions.DefiningTimeToBeReceivedAs(type =>
type.Name.EndsWith("Expires")
        ? TimeSpan.FromSeconds(30)
        : type.GetCustomAttribute<TimeToBeReceivedAttribute>(false)?.TimeToBeReceived ?? TimeSpan.MaxValue
);

Encapsulated conventions

Messaging conventions can be encapsulated into a class.

class MyNamespaceMessageConvention : IMessageConvention
{
    public bool IsMessageType(Type type) => type.Namespace == "MyNamespace.Messages";
    public bool IsCommandType(Type type) => type.Namespace == "MyNamespace.Messages.Events";
    public bool IsEventType(Type type) => type.Namespace == "MyNamespace.Messages.Commands";
    public string Name { get; } = "MyNamespace message convention";
}

These conventions can be added to the endpoint.

endpointConfiguration.Conventions().Add(new MyNamespaceMessageConvention());

Multiple encapsulated conventions can be applied to the same endpoint. A class will be a considered a message, command, or event if any convention matches it.

Attributes

If attributes are preferred over marker interfaces then this can be achieved using NServiceBus.AttributeConventions, a community package that allows using attributes instead of interfaces.

Related Articles

  • Messages, events, and commands
    Messages as commands or events are the the unit of communication for message-based distributed systems. NServiceBus ensures they are used correctly.
  • Unobtrusive Mode Messages
    How to avoid referencing NServiceBus assemblies from message assemblies.