Introduction
This tip describes how to configure different email providers like SMTP, Gmail or any other third party email sender, without changing existing code in one liner plug & play email providers by using Microsoft Managed Extensibility Framework (MEF).
MEF Background
Basically MEF is a component of .NET Framework 4.0 for creating lightweight, extensible applications. MEF allows your application to be extended using components. MEF can be used for third-party plugin extensibility, or it can bring the benefits of a loosely-coupled plugin-like architecture to applications.
Basic Terminology Used
Import
- This attribute is placed above a property to tell the system that something gets plugged in here. E.g. The following statement means IEmail
interface is going to get plugged.
[Import]
IEmail EmailSender;
Export
- This attribute is placed above a class, method, or property/interface to indicate that this is an item to be plugged in somewhere. E.g. The following statement states that Interface IEmail
is going to exported or plugged in somewhere.
[Export]
public interface IEmail
ImportMany
- ImportMany
is a way to express that you want to import all “items” into a type. E.g. multiple export instances into one import by using ImportMany
.
[ImportMany]
IEnumerable<IEmail> EmailSenders;
InheritedExport
- Any class that inherits from the item marked with InheritedExport
will be exported. E.g. The following Interface IEmail
, whichever class inherits this interface will get exported.
[InheritedExport(typeof(IEmail))]
public interface IEmail
- Composition container - Manages the composition of parts, i.e., matching up of import to export parts.
DirectoryCatalog
- All the exports in all the assemblies in a directory. PartNotDiscoverable
- You don’t want a particular component to be discovered by the catalog, so use this attribute to hide the component.
Using the Code
The simplest way to see how MEF works to build a simple MEF application, here I have created a sample application to configure email provider, i.e., plug and play email providers by using MEF.
Please refer to the attached application containing the following projects:
MEF.Contract
- This is common library containing interface abstract
method to send email.MEF.EmailSender
- This class library will manage import export part. Manages email sending functionality like dynamically set provider.MEF.Email.SMTP
- This is SMTP provider which references common IEmail
interface and sends email using SMTP as server. MEF.Email.Gmail
- This is provider which references common IEmail
interface and sends email using GMail as server.- Email Testing (Website) - This is a client application which uses
MEF.EmailSender
library and sends email, using dynamically set provider.
Following are the details of classes being used in this application:
MEF.Contract
- This contains the common interface IEmail
. This library also contains the class EmailInfo
; common properties to send email like To, From, CC, Bcc, etc.
We need to add reference of the following namespaces to have MEF related classes.
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
[InheritedExport(typeof(IEmail))]
public interface IEmail
{
string ProviderName{get;}
bool SendEmail(EmailInfo emailInfo);
}
MEF.EmailSender
- This is the heat of this application, containing the class Program.cs which manages the composition of MEF.
public class Program
{
[ImportMany]
IEnumerable<IEmail> EmailSenders;
private CompositionContainer _container;
public void Compose()
{
AggregateCatalog catalog = new AggregateCatalog();
string directoryPath = @"D:\\Providers";
catalog.Catalogs.Add(new DirectoryCatalog(directoryPath, "*.dll"));
_container = new CompositionContainer(catalog);
_container.ComposeParts(this);
}
public bool SendEmail(string providerName, EmailInfo ObjEmail)
{
Program prog = new Program();
prog.Compose();
foreach (var item in prog.EmailSenders)
{
if (item.ProviderName.ToUpper() == providerName.ToUpper())
{
return item.SendEmail(ObjEmail);
}
}
return true;
}
}
MEF.Email.SMTP
/MEF.Email.Gmail
- This library will inherit from the IEmail
provider and set the actual implementation code here:
public class SMTPSender : IEmail
{
private string _ProviderName = "SMTP";
public bool SendEmail(EmailInfo emailInfo)
{
MailMessage message = new MailMessage();
message.To.Add(emailInfo.To);
message.Subject = emailInfo.Subject;
message.From = new System.Net.Mail.MailAddress(emailInfo.From);
message.Body = emailInfo.Body;
SmtpClient smtp = new SmtpClient("localhost");
try
{
smtp.Send(message);
return true;
}
catch(Exception ex)
{
return false;
}
}
public string ProviderName
{
get
{
return _ProviderName;
}
}
}
EmailTesting
- This is a client application website; containing a call to MEF.EmailSender SendEmail
method, which will send the email.
private void SendEmail()
{
EmailInfo emailInfo = new EmailInfo();
emailInfo.To = txtTo.Text.Trim();
emailInfo.From = txtFrom.Text.Trim();
emailInfo.Subject = txtSubject.Text;
emailInfo.Body = txtBody.Text;
Program obj = new Program();
obj.SendEmail(ddlEmailServer.SelectedValue, emailInfo);
}
Interesting Points
- We can easily plug-in any third party email sender. MEF is useful in a plugin architecture where third party code has limited access to your application. This is designed for extensibility purposes.
- Here the Components/Email provider can be added at run-time, you just need to deploy a new provider DLL in the configured folder.