Mef2P4 MVC3 integration: Providing custom conventions

Nov 1, 2011 at 5:30 PM

The MvcApplicationCatalog defines a set of conventions for MVC apps using the new RegistrationBuilder API. Is it possible to extend/override these conventions without providing a completely new catalog? The MvcApplicationCatalog class is small and I believe it mostly exists just to provide these conventions, so it would not be difficult to create a new catalog that contained these conventions and your own custom ones, or perhaps create an aggregate catalog that contains the MvcApplicationCatalog plus a custom catalog with custom conventions. Is that the expected way to provide custom conventions?

Nov 1, 2011 at 5:39 PM

Hi – yes, that’s correct. The MvcApplicationCatalog is deliberately ‘closed’ because providing a reliable way to modify its conventions would be more complicated than simply creating a new one using RegistrationBuilder.

As an example, if I wanted to register controllers but only one specific part (excluding the ‘Parts’ namespaces) I would use the following in Application_Start():

var builder = new RegistrationBuilder();

builder.ForTypesDerivedFrom<IController>().Export();

builder.ForType<Foo>().Export<IBar>();

var catalog = new AssemblyCatalog(typeof(MyMvcApplication).Assembly, builder);

CompositionProvider.SetCatalog(catalog);

Let me know if this meets your requirements, thanks!

Nick

From: pwideman [email removed]
Sent: Tuesday, November 01, 2011 10:31 AM
To: Nicholas Blumhardt
Subject: Mef2P4 MVC3 integration: Providing custom conventions [MEF:277914]

From: pwideman

The MvcApplicationCatalog defines a set of conventions for MVC apps using the new RegistrationBuilder API. Is it possible to extend/override these conventions without providing a completely new catalog? The MvcApplicationCatalog class is small and I believe it mostly exists just to provide these conventions, so it would not be difficult to create a new catalog that contained these conventions and your own custom ones, or perhaps create an aggregate catalog that contains the MvcApplicationCatalog plus a custom catalog with custom conventions. Is that the expected way to provide custom conventions?

Nov 1, 2011 at 8:00 PM

Thanks, I have implemented something similar with success, for the most part. Here are a couple of things I ran into:

1. I build the catalog given to CompositionProvider by creating a list of AssemblyCatalogs that I apply my own conventions to, then creating an MvcApplicationCatalog over the same list of assemblies, to apply the default MVC conventions. This results in duplicate exports if a type matches both sets of conventions, or if it is exported with attributes (at least it does in my testing, someone let me know if there's a better way to do this that won't result in duplicates). Of course I can look at the MEF code and easily reproduce the default conventions in my own set, but this may present a problem in the general case. It would be nice to be able to apply both the system defaults and my own conventions easily.

2. The CompositionProvider reads metadata to determine which exports are application scope, and this metadata is generated by the MvcApplicationCatalog conventions looking for the ApplicationShared attribute. The metadata name that CompositionProvider keys on is defined as an internal string const. This presents a dilemma: just applying the ApplicationShared attribute to exports doesn't have the desired result unless the export is picked up by the MvcApplicationCatalog's conventions, but I cannot repeat said convention in my own code because I don't have access to the metadata name value. Of course I can hack around it by copying the magic string into my own code, but that is obviously error prone. Is there a way to use this functionality in the current build, that I'm just missing? If not, I would like to see two things:

a. The ApplicationShared attribute honored without having to do anything else, even if I build my own conventions for other things

b. An "InApplicationScope" method added to PartBuilder to encapsulate this functionality when building my own conventions, and the attribute is not present

Nov 1, 2011 at 8:20 PM

Thanks – I think at a minimum we should expose the string constant as a public field. I agree that it would be nice to make supporting [ApplicationShared] easier in a hand-built convention, we’ll definitely give it some thought.


Cheers,
Nick

From: pwideman [email removed]
Sent: Tuesday, November 01, 2011 1:00 PM
To: Nicholas Blumhardt
Subject: Re: Mef2P4 MVC3 integration: Providing custom conventions [MEF:277914]

From: pwideman

Thanks, I have implemented something similar with success, for the most part. Here are a couple of things I ran into:

1. I build the catalog given to CompositionProvider by creating a list of AssemblyCatalogs that I apply my own conventions to, then creating an MvcApplicationCatalog over the same list of assemblies, to apply the default MVC conventions. This results in duplicate exports if a type matches both sets of conventions, or if it is exported with attributes (at least it does in my testing, someone let me know if there's a better way to do this that won't result in duplicates). Of course I can look at the MEF code and easily reproduce the default conventions in my own set, but this may present a problem in the general case. It would be nice to be able to apply both the system defaults and my own conventions easily.

2. The CompositionProvider reads metadata to determine which exports are application scope, and this metadata is generated by the MvcApplicationCatalog conventions looking for the ApplicationShared attribute. The metadata name that CompositionProvider keys on is defined as an internal string const. This presents a dilemma: just applying the ApplicationShared attribute to exports doesn't have the desired result unless the export is picked up by the MvcApplicationCatalog's conventions, but I cannot repeat said convention in my own code because I don't have access to the metadata name value. Of course I can hack around it by copying the magic string into my own code, but that is obviously error prone. Is there a way to use this functionality in the current build, that I'm just missing? If not, I would like to see two things:

a. The ApplicationShared attribute honored without having to do anything else, even if I build my own conventions for other things

b. An "InApplicationScope" method added to PartBuilder to encapsulate this functionality when building my own conventions, and the attribute is not present