tags:

views:

437

answers:

2

I have an asp.net application using a model assembly (with a Model class) for business logic. This model assembly has a dependency on a MailService through an IMailService interface and I am trying to use MEF to fill the Models need for a MailService implementation. I am doing the MEF composition in the contructor of the Model class.

The idea behind this is to create a MailService assembly I can reuse between my websites without the sites themselves need to know how the mail is sent. Maybe an IoC container would be a better choise but I just think the MEF approach is simpler to understand and I like the idea of composing my apps by combining parts. Also does the mef approach have any negative sides if you compare with a IoC container?

[Import]
private IMailService _mailService;

public Model()
{
    Compose();
}

private void Compose()
{
     DirectoryCatalog cat = new DirectoryCatalog(Settings.Default.PluginsFolder);
     var container = new CompositionContainer(cat);
     container.ComposeParts(this);
}

The code below is in another assembly and the interface in yet another assembly

[Export(typeof(IMailService))]
public class MailService : IMailService
{
}

this works fine in my unit tests for the model assembly but when I am using the model assembly through my asp.net site it fails with the exception below. I also tried to set the trust to full in web.config but still no luck

The composition remains unchanged. The changes were rejected because of the following error(s): The composition produced a single composition error. The root cause is provided below. Review the CompositionException.Errors property for more detailed information.

1) No exports were found that match the constraint '((exportDefinition.ContractName = "ExtensionInterfaces.IMailService") && (exportDefinition.Metadata.ContainsKey("ExportTypeIdentity") && "ExtensionInterfaces.IMailService".Equals(exportDefinition.Metadata.get_Item("ExportTypeIdentity"))))'.

Resulting in: Cannot set import Model.Model._mailService (ContractName="ExtensionInterfaces.IMailService")' on part Model.Model'. Element: Model.Model._mailService (ContractName="ExtensionInterfaces.IMailService") --> Model.Model

+1  A: 

I've not used MEF in a web application yet, but if I were to guess I would assume there is some issue with reading the assemblies in the plugins directory. Maybe an permissions issue or something. At any rate I would start by examining the DirectoryCatalog to see if it contains what you would expect it to.

Wes Haggard
I suspected that as well, I gave Everyone full access to that folder, set the website to full trust. I even moved the plugins folder inside the website but still no luck.
TT
Also the unit test calling that spesific code works fine, so its a problem that occurs when using a asp.net site as a client
TT
A: 

I found the error, I had a assembly in the bin folder with the same name as the MailService assembly with my export. For some reason the catalog picked up the assembly in the bin folder instead of the assembly in the catalog I specified. Don't know why but it worked when I removed the old assembly from the bin folder at least.

TT
It could have possibly accured if the old assembly was loaded in the process and the old and new assembly have the exact same identity (i.e. Assembly Name, Version, Key, etc). The DirectoryCatalog simply does an Assembly.Load(AssemblyName) and if the assembly with the same identity is already loaded in the AppDomain it would simply use the already loading assembly instead of loading the new even if they contain different code.
Wes Haggard