Limit exports that are imported

Sep 10, 2010 at 5:30 AM

I am having some troubles with something related to MEF in a Silverlight 4 application that I am working on.  I have a Logger class that relies on various providers (ILoggerProvider) to actually write the log.  The Logger class IMPORTs the providers.  This all works fine but I have multiple providers in my assemby so they are all imported and each is written to when the Logger is used.  I want to be able to specify which of the providers should be used rather than having them all be imported.  I have been researching this for the past two days and have tried everything I could find but none of the samples seem to be helping me out.

The thing I just tried was using a custom ExportProvider but I think I am missing something.  I am using an AssemblyCatalog to get all the assemblies, which works great.  Now I need somewway to not return all exports but rather return all exports that are not ILoggerProviders as well as just the specified ILoggerProvider.

Any input would really help me out.  This is starting to kill me.

Todd

Sep 10, 2010 at 6:11 AM

Hi Todd

This might be a good match for using a Filtered Catalog. With a filtered catalog you can specify an expression that limits the parts that are returned based on an expression. See the wiki page on that here:

Glenn

 

Sep 10, 2010 at 6:42 AM

Thanks Glenn.  I am super tired at the moment so I will try that out in the morning.

I did just notice something else that is bothering me though.  My "Providers" property that has the ImportMany attribute is importing my Providers.  When I compose my parts (using CompositionInitializer.SatisfyImports() I look at this property and it shows 4 items when I only have two classes that export ILoggerProvider.  It has two copies of both classes.  As a test, I currently only have the call to SatisfyImprots (with no other catalogs involved) just so I could test.  Initially I had an aggregate catalog which contained an assembly catalog  and I passed this into CompositionHost.Initialize().  Another time, I created a contained passing it an AssemblyCatalog and then passed the container to CompositionHost.Initialize.  All of these have the same result.  My call to satisfyimports only occurs once and I have checked many times that I only have two imports. 

What could be causing this issue?

Todd

Sep 10, 2010 at 5:17 PM

Ok.  I have made a stab at the FilteredCatalog but I am having another issue.  I limited the filter function in an attempt to keep things simple.  Right now I am just checking for the existence of a metadata key called "ID".  My code is: 

 


new FilteredCatalog(assemblyCatalog, 
                    def => (def.Metadata.ContainsKey("ID"))));

I have a break point set in the FilterCatalog and I see that the _partsQuery being returned is empty.  I have confirmed that the Parts collection actually has 3 parts and two of them have the ID metadata key.  I confirmed this but for some reason the Where statement is still returning nothing.  I am not sure what I could be doing incorrectly.  While debugging I actually took a close look at the Parts collection and I saw that two of the MetaData collections do contain the "ID" key.  If I output "def.Metadata.ContainsKey("ID")" to the Immediate window it returns true but, again, when I let the Where clause execute, it still returns an empty collection.

Thanks,

Todd

Sep 10, 2010 at 6:24 PM

Nevermind on this one.  I forgot about the fact that LINQ queries don't automatically execute.  Opps.  Sorry.  Long night.  Hopefully I can get this working now.

Sep 10, 2010 at 8:44 PM

I have two filtered catalogs at work now.  The first one gives me the correctLoggerProvider part and the second give me the correct PreferencesProvider part.  This is working great until I try to recompose the LoggerProvider.  The issue is that I need to use my Logger (with default Provider) before it is actually configrued.  This works.  Once configuration kicks in I attempt to recompose the part by calling CompositionInitializer.SatisfyImports() on it.  This is throwing an exception saying that it can't recompose them.  The exception says:

1) More than one export was found that matches the constraint '((exportDefinition.ContractName == "Berico.LinkAnalysis.SnagL.Logging.Providers.ILoggerProvider") AndAlso (exportDefinition.Metadata.ContainsKey("ExportTypeIdentity") AndAlso "Berico.LinkAnalysis.SnagL.Logging.Providers.ILoggerProvider".Equals(exportDefinition.Metadata.get_Item("ExportTypeIdentity"))))'

I don't get this error the first time through.  I also, technically, want to only recompose the catalogs related to the LoggerProviders (not any other ones).  Any advice here would be much appreciated.