Yesterday afternoon [Feb-6th-2010] I spent some time chatting to Glenn Block, Program Manager of MEF. After that i thought let’s blog on this MEF here it is.
What is MEF?
Managed Extensibility Framework (MEF) is the new library framework from Microsoft to build Plug-In or adding classes to the application at run-time. MEF is part of .NET 4.0 and its not application specific you can use it any .NET Application like Windows Forms, WPF , SilverLight ,ASP.NET etc. MEF lives in side the following .NET assembly.
MEF is all about Export , Import and Compose. Now let us explore the MEF developing by Simple application.
[Export]- Describes a capability that a part has to share in the composition
[Import] – Describes a compositional dependency that a part has. This is a requirement that a part needs to have satisfied when it participates in composition
]
The above Figure shows that the Main Application and Plug-In do not know each other existence and the Contract assembly is required to integrate both the assemblies.
Here i am going to build small email client application initially it sends only Text Format based emails, after that we are going to see how MEF can help to support other format like HTML , Video &HTML etc.
First let us defined the Interface with one method called Send() as shown below.
public interface IMailMessage
{
void Send(EmailMessage msg);
}
Export
[Export(typeof(IMailMessage))]
public class TextBasedFormat : IMailMessage
{
StringBuilder sbmsg = new StringBuilder();
string msgTo = string.Empty;
public void Send(EmailMessage msg)
{
sbmsg.AppendFormat("To :{0}", msg.To);
sbmsg.AppendFormat("\nFrom:{0}", msg.From);
sbmsg.AppendFormat("\nSubject:{0}", msg.Subject);
sbmsg.AppendFormat("\nMessage Body :{0}", msg.Message);
sbmsg.Append("\n\n");
sbmsg.AppendFormat("\nThanks \n{0}", msg.From);
msgTo = @"C:\Appdev\" + msg.To + ".txt";
StreamWriter sw = new StreamWriter(msgTo);
sw.WriteLine(sbmsg.ToString());
sw.Flush();
sw.Close();
}
}
Import:
[Import(typeof(IMailMessage))]
public IMailMessage MailPlugIn { get; set; }
Compose: (HOSTING)
Here we have asked our application to find all the plug-in (classes with ‘Export’ attributes) from the currently executing assembly. because our plug-in [Export] resides in the same application. Suppose if we implement our Plug-In in separate assembly and the output assembly we can copy to some directory (example: myPlugIn) in this case our Plug-in resides inside directory now we need to use DirectoryCatalog.
AggregateCatalog :Suppose if our Plug-Ins are coming from two different source (Same Assembly,Directory ) then we need use AggregateCatalog to combine both the Assembly parts.
Here is the object view for the Plug-in Hosting .
public void ComposeParts()
{
var catalog =new AssemblyCatalog((Assembly.GetExecutingAssembly()));
var container = new CompositionContainer(catalog );
container.ComposeParts(this);
}
My Email Application user Interface.
On Send Button Click i am calling Send() method
private void Button_Click(object sender, RoutedEventArgs e)
{
EmailMessage msg = new EmailMessage ();
msg.To = txtTo.Text;
msg.From = txtFrom.Text;
msg.Subject = txtSub.Text;
msg.Message =txtMsg.Text ;
MailPlugIn.Send(msg);
MessageBox.Show("Message has been sent..");
}
Now let us build HTML based Plug-in.
[Export(typeof(IMailMessage))]
public class HTMLBasedFormat : IMailMessage
{
StringBuilder sbmsg = new StringBuilder();
string msgTo = string.Empty;
public void Send(EmailMessage msg)
{
sbmsg.Append("\n<html><head><title>Message</title></Head><body>");
sbmsg.AppendFormat("<h2>To :{0}</h2>", msg.To);
sbmsg.AppendFormat("\n<h2>From:{0}</h2>", msg.From);
sbmsg.AppendFormat("\nSubject:{0}", msg.Subject);
sbmsg.AppendFormat("\n<p>Message Body :{0}</p>", msg.Message);
sbmsg.Append("\n\n");
sbmsg.AppendFormat("\nThanks \n{0}", msg.From);
sbmsg.Append("</Body></Html>");
msgTo = @"C:\Appdev\" + msg.To + ".html";
StreamWriter sw = new StreamWriter(msgTo);
sw.WriteLine(sbmsg.ToString());
sw.Flush();
sw.Close();
}
Now we have two compose able parts to import inside our application, so now we need to use [ImportMany] attribute. that is from single part to collection of parts.
[ImportMany(typeof(IMailMessage))]
public IEnumerable<IMailMessage> MailPlugIn { get; set; }
private void Button_Click(object sender, RoutedEventArgs e)
{
EmailMessage msg = new EmailMessage ();
msg.To = txtTo.Text;
msg.From = txtFrom.Text;
msg.Subject = txtSub.Text;
msg.Message =txtMsg.Text ;
// Enumerate all the pulgin
foreach (var item in MailPlugIn )
{
item.Send(msg);
}
MessageBox.Show("Message has been sent..");
}
TESTING:
Both Message format files are created
[Note: Here I am sending email to windows folder to mimic ]
Next blog post we will see how to use Directory and aggregate Catalogs.
Nandri(Thanks)
Sreenivasaragavan.