![]() |
Platforms, Frameworks & Libraries »
Libraries »
General
Beginner
License: The Code Project Open License (CPOL)
Managed Extensibility Framework: Part 2By Sriharsha VardhanManaging information flow between an extension and an application. |
C# 1.0, C# 2.0, C# 3.0WinXP, Win2003, .NET 4.0, Architect, Dev
|
|
Advanced Search Add to IE Search |
|
|
|
||||||||||||||||
This is in continuation with my previous post in this series. Part 1 covered the problem MEF tried to solve. In this part, we will see how MEF solves the problem scenario described in Part 1.
The example covers the scenario where information flows from application to an extension as well as from an extension to the application. In MEF terms, an extension is a composable part or simply a part. I chose to exchange a custom class instead of built-in types like string or int. I intended to cover the exchange of events as well. But, I will hold the events for the next part.
At the end of Part 1, I showed a working code that could be used as a managed extension. But, that solution is at a lower level and is not so very flexible. MEF provides discoverable catalogs to search parts from various sources like DirectoryCatalog or AssemblyCatalog. And, the container takes the responsibility to co-ordinate the catalog to match export/import pairs. More information about this can be found at http://mef.codeplex.com/Wiki/View.aspx?title=Overview.
The code for this example is available in three solutions. The console application can consume an extensible parts class library which contains the contract, and the interfaces class library contains one of the extensible parts that implements the contract. And, you just need one library from the MEF framework. As of now, MEF is all in one DLL named System.ComponentModel.Composition. You can download this framework from CodePlex. OK, let us implement these three solutions.
Here, we build a console application which can consume an extensible part. This application even exports a part.
using System;
using System.IO;
using System.Reflection;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.ComponentModel.Composition.Primitives;
namespace meflab1
{
class Program
{
[Import]
public IGreetings Greetings { get; set; }
static void Main(string[] args)
{
Console.WriteLine("Enter 0 to quit, any other number to continue");
while (Console.ReadLine() != "0")
{
Program program = new Program();
program.Compose();
program.Run();
}
}
void Compose()
{
try
{
DirectoryCatalog catalog =
new DirectoryCatalog(AppDomain.CurrentDomain.BaseDirectory);
AggregateCatalog agcatalogue =
new AggregateCatalog(new ComposablePartCatalog[] {catalog,
new AssemblyCatalog(Assembly.GetExecutingAssembly())});
CompositionContainer container = new CompositionContainer(agcatalogue);
CompositionBatch batch = new CompositionBatch();
batch.AddPart(this);
container.Compose(batch);
}
catch (FileNotFoundException fnfex)
{
Console.WriteLine(fnfex.Message);
}
catch (CompositionException cex)
{
Console.WriteLine(cex.Message);
}
}
void Run()
{
if (Greetings != null)
{
Console.WriteLine(Greetings.SayHello());
}
Console.Read();
}
}
}
Add a class by name SimpleGreeting and replace the code in SimpleGreeting.cs with the following snippet:
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
namespace meflab1
{
[Export(typeof(IContextInfo))]
public class UserInfo : IContextInfo
{
public IDictionary<string,> GetContextInfo()
{
return new Dictionary<string,> { { "UserName",
Environment.UserDomainName + "\\" + Environment.UserName } };
}
}
}
Save this solution.
We are just defining two interfaces here:
using System.Collections.Generic;
namespace meflab1
{
public interface IContextInfo
{
IDictionary<string,> GetContextInfo();
}
public interface IGreetings
{
string SayHello();
}
}
Build it and add a reference of this class library to the application we built in the previous section.
Here, we are implementing one of the extensible parts:
using System.ComponentModel.Composition;
namespace meflab1
{
[Export(typeof(IGreetings))]
public class SimpleGreeting : IGreetings
{
[Import(typeof(IContextInfo))]
public IContextInfo ContextInfo { get; set; }
public string SayHello()
{
string userName;
var props = ContextInfo.GetContextInfo();
props.TryGetValue("UserName", out userName);
return "Hello " + (userName ?? "<null>") +
" from Visual Studio 2010";
}
}
}
Build it!
Having this infrastructure in place lets us do two exercises.
Now, build the first solution and try to run it.
We end up with the following error:
The composition produced a single composition error. The root cause is provided below.
Review the CompositionException.Errors property for more detailed inf
ormation.
1) No exports were found that match the constraint
'((exportDefinition.ContractName = "meflab1.IGreetings") &&
(exportDefinition.Metadata.ContainsKey("Expor
tTypeIdentity") && "meflab1.IGreetings".Equals(exportDefinition.Metadata.get_Item
("ExportTypeIdentity"))))'.
Resulting in: Cannot set import 'meflab1.Program.Greetings
(ContractName="meflab1.IGreetings")' on part 'meflab1.Program'.
Element: meflab1.Program.Greetings (ContractName="meflab1.IGreetings")
--> meflab1.Program
This is expected as we don't have any library implementing the IGreetings interface.
Observe that the application could seamlessly load the part and execute the code in it. So, what didn't work in part-1 works now.
I will explain the exchange of events and some scenarios (point 2 in the next section) where MEF fails and why it fails to load, in my next post.
AggregateCatalog is used because the application exports 'UserInfo', and thus even
the current assembly needs to be added to the catalog.Unhandled Exception: System.Reflection.ReflectionTypeLoadException:
Unable to load one or more of the requested types.
Retrieve the LoaderExceptions property for more information.
| You must Sign In to use this message board. | ||||||||
|
||||||||
|
||||||||
|
||||||||
|
||||||||
General
News
Question
Answer
Joke
Rant
Admin
|
PermaLink |
Privacy |
Terms of Use
Last Updated: 23 Jun 2009 Editor: Smitha Vijayan |
Copyright 2009 by Sriharsha Vardhan Everything else Copyright © CodeProject, 1999-2009 Web22 | Advertise on the Code Project |