I have created a class library (assembly) that provides messaging, email and sms. This class library defines an interface IMessenger which the classes EmailMessage and SmsMessage both implement.
I see this is a general library that would be part of my infrastructure layer and would / can be used across any development.
Now, in my application layer I have a class that requires to use a messaging component, I obviously want to use the messaging library that I have created. Additionally, I will be using an IoC container (Spring.net) to allow me to inject my implementation i.e. either email or sms.
Therefore, I want to program against an interface in my application layer class, do I then need to reference my message class library from my application layer class?
Is this tightly coupling my application layer class to my message class library?
Should I be defining the interface - IMessenger in a seperate library?
Or should I be doing something else?
There is nothing wrong with referencing (and thus coupling) the application layer class to the message library. As long as your message library is independent and unaware of its users it is fine.
Moreover, dont over-architect just for the fact of architecture. It should have a purpose and the benefits should be greater than the costs.
My answers to your questions:
"Therefore, I want to program against an interface in my application layer class, do I then need to reference my message class library from my application layer class?" NO
"Is this tightly coupling my application layer class to my message class library?" YES
"Should I be defining the interface - IMessenger in a seperate library?" YES
If you're using an IoC container, PLEASE inject the dependencies and don't couple your app to infraestructure implementations.
My implementation would be to put the IMessenger interface in the application layer, in order to allow my app objects to talk to an interface, no matter its implementations. I would have the general email and SMS sending in a separate assembly, and they implement IMessenger. The injection, obviously, is performed by an IoC container.
The application layer shouldn't know the infraestructure layer.
This is a good page to see this kind of designs: Hexagonal Architecture.
It all depends on what your future plans for IMessenger are. Personally I do not find that having the interface as well as a few sample implementations in the same assembly is a bad thing. If someone wants to provide a new implementation of IMessenger they will have to do it in another assembly, and in the course of bringing in your assembly they will get EmailMessage, SmsMessage, etc. For a lightweight assembly I view that as not a big deal, since it saves you the effort of referencing both your "interface" and "implementation" assemblies every time you want to use one.
If your implementation classes reference other code related to your organization or anything that you wouldn't want exposed, then it would make more sense to separate IMessenger into its own assembly and just distribute that as needed.