MEF will not help you solve extensibility issues in the case you have described in the question, because it doesn't seem to have any. What MEF can bring to the table for this particular case is Dependency Injection. If you develop your application in a way that the presentation layer depends on business abstraction and the business layer depends on a data access abstraction rather than on concrete implementation, you will get a highly decoupled application that is easy to test, maintain and change without affecting unnecessary components. Here is one way to do this:
Lets say you have data access class that performs CRUD operations on employees:
[Export(typeof(IEmployeeRepository))]
public class EmployeeRepository : IEmployeeRepository
{
//Some logic here
}
As you can see the EmployeeRepository
class implements IEmployeeRepository
interface which adds the level of abstraction that is needed to develop a decoupled application. Now lets say that in the business layer you have a class that needs to call some method from the EmployeeRepository
class. To be able to call a method of EmployeeRepository
, you would need an instance of it. Without using MEF (or any other IoC framework, this would be a way to do it:
public class EmployeeManager
{
private EmployeeRepository _employeeRepository;
public EmployeeManager
{
_employeeRepository = new EmployeeRepository();
}
}
By using the above code sample, a hard dependency between the EmployeeManager
and EmployeeRepository
classes is created. This hard dependency is difficult to isolate when writing unit tests and causes any change of the EmployeeRepository
class to directly affect the EmployeeManager
class. By refactoring the code sample a little bit and putting MEF into the game, you'll get this:
[Export(typeof(IEmployeeManager))]
public class EmployeeManager : IEmployeeManager
{
private IEmployeeRepository _employeeRepository;
[ImportingConstructor]
public EmployeeManager(IEmployeeRepository employeeRepository)
{
_employeeRepository = employeeRepository;
}
}
As you can see the EmployeeManager
class now doesn't depend on the EmployeeRepository
class, but it depends on IEmployeeRepository
interface, in other words it depends on abstraction. And it doesn't create the instance of EmployeeRepository
class by itself. That job is left to MEF. By now it should be clear that export and ImportingConstructor
attributes are part of MEF and are used by it to discover parts and resolve dependencies at runtime. With the last code sample the classes are decoupled, easy to test and maintain and you can change the internal logic in EmployeeRepository
class without making EmployeeManager
class aware of it. Of course the contract between them, IEmployeeRepository
have to be maintained.
The above said, can be used to decouple the presentation layer from the business layer also. Also the above said, can be implemented by using any other IoC framework, like Ninject, Autofac, StructureMap etc. The difference between these IoC frameworks and MEF is that if you use them, you'll need to configure at application start which instance gets created when some interface is encountered:
//something like this, in the case of Ninject
this.Bind<IEmployeeRepository>().To<EmployeeRepository>();
On the other hand, MEF has the ability to discover parts at runtime. On application start, you'll just need to inform it where to look for parts: Directory, Assembly, Type etc. The auto-wire capabilities of MEF (the ability to discover parts at runtime), make it more than a regular IoC framework. This ability makes MEF great for developing pluggable and extensible applications because you'll be able to add plugins while the application is running. MEF is able load them and let the application to use them.