I'm doing some initial investigation into decomposing a current monolithic system by using MassTransit. My main reason for going with a queue-based ESB is that the set of features I'm tackling first are using a shared database as, essentially, a queue.
I've also been reading "Building Microservices" and while I haven't yet finished it, one of the core tenets appears to be that microservices should essentially be standalone.
How can I reconcile using MassTransit which by necessity shares a message library (or at least contracts) and the fact that these services shouldn't have to "know" anything about each other?
The question is really about coupling. How coupled are your various services? 'Standalone' implies a level of loose coupling, but in order to interoperate, some level of coupling is required. The challenge is to couple as loosely as possible whilst maintaining the interoperability that will allow your components to work together to achieve your desired outcome.
A coupling via message contracts is a loose coupling. This only requires that each of your services knows and understands the 'shape' of the data (messages) that passes between them. The services have no need to share any code, hosts or even platforms.
When using an ESB, this shared knowledge of messages is the only thing that your services need to 'know' about each other. Depending on the type of transport you use, you may also need to give each service knowledge of the location (URI) of the other services, but again, this is a very loose coupling (spatial) and can be loosened further by, e.g. DNS. If you choose to use a brokered transport, e.g. centralised queuing technology like RabbitMQ, then this spatial coupling can be removed, but this comes with other trade-offs.
Bear in mind that MassTransit is not the only option available in the .NET space. E.g. a popular choice is NServiceBus (full disclosure: I work for Particular Software and NSB is one of our products).