Sunday, February 7, 2010

The MEF [Managed Extensibility Framework] Series Part-1

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.

image

MEF is all about  Export , Import and ComposeNow 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

  ]image

image

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 .


image 


public void ComposeParts()
{
var catalog =new AssemblyCatalog((Assembly.GetExecutingAssembly()));
var container = new CompositionContainer(catalog );
container.ComposeParts(this);

}


image



My Email Application user Interface.



image



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:


image 


Both Message format files are created 


image 



[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.

No comments: