# Conventions *Conventions* identify message, command, and event types without [marker interfaces](/nservicebus/messaging/messages-events-commands.md#identifying-messages-marker-interfaces). Using conventions for message identification is called *[unobtrusive mode](unobtrusive-mode.md)*. > [!NOTE] > For new message contracts with NServiceBus 8 or later, prefer the marker interfaces in the [NServiceBus.MessageInterfaces package](https://www.nuget.org/packages/NServiceBus.MessageInterfaces). The package avoids a dependency on the NServiceBus assembly while supporting shared message assemblies across major NServiceBus versions and .NET target frameworks. Use conventions when existing message types cannot implement marker interfaces or when conventions are needed for other features. See the [sharing message assemblies sample](/samples/message-assembly-sharing/index.md). Currently, *conventions* exist to identify: - [Commands](/nservicebus/messaging/messages-events-commands.md) - [Events](/nservicebus/messaging/messages-events-commands.md) - [Messages](/nservicebus/messaging/messages-events-commands.md) - [Message Property Encryption](/nservicebus/security/property-encryption.md) - [Data Bus](/nservicebus/messaging/claimcheck/index.md) - [TimeToBeReceived](/nservicebus/messaging/discard-old-messages.md) 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. ```cs 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); ``` > [!NOTE] > In .NET, the namespace is optional and can be null. If any conventions do partial string checks, for example using `EndsWith` or `StartsWith`, then a null check should be used. Include `.Namespace != null` at the start of the convention to avoid a null reference exception during type scanning. ## 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. ```cs 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(false)?.TimeToBeReceived ?? TimeSpan.MaxValue ); ``` ## Encapsulated conventions Messaging conventions can be encapsulated into a class. ```cs 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. ```cs endpointConfiguration.Conventions().Add(new MyNamespaceMessageConvention()); ``` Multiple encapsulated conventions can be applied to the same endpoint. A class will be considered a message, command, or event if any convention matches it. > [!NOTE] > Adding an instance of `IMessageConvention` does not override the default conventions. ## Attributes If attributes are preferred over marker interfaces, use [NServiceBus.AttributeConventions](https://github.com/mauroservienti/NServiceBus.AttributeConventions), a [community package](/nservicebus/community/index.md) that allows using attributes instead of interfaces.