Touble with TypeCatalog

Sep 10, 2010 at 7:13 PM

For some reason I am having difficulty with the TypeCatalog.  I user this line of code to create my catalog:

new TypeCatalog(typeof(ILoggerProvider))

Even thought my assembly contains two classes that inherit from ILoggerProvider, the TypeCatalog never has any parts.  Any thoughts?

Sep 10, 2010 at 7:36 PM

Actually, I just did further research and it seems you can't do it with an interface.  So, my question now is what is the best way to split up my catalogs.  I need to apply a filter to a catalog to retrieve the appropriate loggers.  I have to do this with preference providers as well.  Then I need all other exports that are neither loggers or preference providers.  Right now I have an assemblyCatalog and create two different filterCatalogs from that.  I need an appropriate way to filter for parts of a specific interface so I can further filter down the loggers and preference providers.  I will then need to create yet another filtercatalog to get all the exports that are neither preference or logger providers.  Is there an easier way to handle this?

Sep 11, 2010 at 12:37 AM
You have to add concrete types ie LoggerProvider which has an export on it. Alternatively LoggerProvider could implement ILoggerProvider which you could put an InheritedExport attribute on.

Sent from my IPad.

On Sep 10, 2010, at 12:14 PM, "TAHerman" <notifications@codeplex.com> wrote:

From: TAHerman

For some reason I am having difficulty with the TypeCatalog. I user this line of code to create my catalog:

new TypeCatalog(typeof(ILoggerProvider))

Even thought my assembly contains two classes that inherit from ILoggerProvider, the TypeCatalog never has any parts. Any thoughts?

Sep 11, 2010 at 2:58 AM

My concrete LoggerProvider class does inheirt the ILoggerProvider interface.  I added the InheritedExport attribute to the interface and remove the Export attribute from the concrete class.  I then tried to use the TypeCatalog against the ILoggerProvider interface but it still doesn't return anything.  I may have misunderstood what your were suggesting.  I may end up with many providers so I didn't want to have to target each concrete class.

Thanks,

Todd

Sep 11, 2010 at 5:44 AM
You can't add the interface to the catalog, you add the concrete type that implements the interface and we discover it ie

public class LoggerProvider : ILoggerProvider {}

[InheritedExport]
public interface ILoggerProvider {}

Then in your init code....

var catalog = new TypeCatalog(typeof(LoggerProvider));

When we look at LoggerProvider we will see it implements ILoggerProvider which has an InheritedExport, and we will create a part definition for it making it available to the container.

Make sense?

Sent from my IPad.

On Sep 10, 2010, at 7:58 PM, "TAHerman" <notifications@codeplex.com> wrote:

From: TAHerman

My concrete LoggerProvider class does inheirt the ILoggerProvider interface. I added the InheritedExport attribute to the interface and remove the Export attribute from the concrete class. I then tried to use the TypeCatalog against the ILoggerProvider interface but it still doesn't return anything. I may have misunderstood what your were suggesting. I may end up with many providers so I didn't want to have to target each concrete class.

Thanks,

Todd

Sep 11, 2010 at 2:33 PM

Thanks Glenn.  I do understand the InheritedExport tag.  I was just misunderstanding that you must target the concrete type with the TypeCatalog.  I was hoping to avoid that.  I might be able to make it work.  I am currently struggling with the logic of it all.  My situation is that my application contains two ILoggerProvider's and that more ILoggerProviders might be available if the customer creates them and adds them externally.  The FilterCatalog is helping me to return the ILoggerProvider that is configured for use.  However, I am having trouble getting all my logiv to work.  My logic is this:

  1. The part must inherit ILoggerProvider.  I am accomplishing this by checking the ContractName of the Part's Export Definition.
  2. The value of the Part's ID metadata field must equal the value that is specified in the configuration.  I accomplish this by checking for the existance of the 'ID' key and comparing the values.
  3. If no value was provided in the configuration or the provided value does not match any of the currently found Parts, use the part defined as the default.

 I have accomplished the first two using the FilterCatalog and this:

(def) => (def.ExportDefinitions.Any(exportDef => exportDef.ContractName.EndsWith("ILoggerProvider"))) && (def.Metadata.ContainsKey("ID") && def.Metadata["ID"].ToString().ToLower().Equals(loggerProvider));

It works great, and I know it executes anytime I recompose it, which is important because I do recompose the loggerprovider at least once.  The issue I am having is accomplishing item 3 listed above.  I need to somehow check if no parts were returned by the above query and then find the default one in that case.  I am not sure where this logic can be applied that recomposition will also perform it.

Thanks,

Todd

Sep 11, 2010 at 3:32 PM
Edited Sep 11, 2010 at 4:06 PM

I would suggest that TypeCatalog may not be the best solution. I  have similar requirements (but  I have multiple MVVM views, rather than logger objects) with view types deriving from the same base class. I found DirectoryCatalog satisfying my requirements just fine. I can request  exports such that contract type derives from a specific base type. Contract name can be any string so there is no guarantee that corresponding type inherits from a particular interface. Sure, you can always slap ContractName authors on the wrist :) but ...

In any case, I don't see why can't you have metadata attribute like:

[ExportMetadata("Iface", typeof(myIface))]

and then filter on the type of Iface key. This requires a bit more attention from contract author than does the contract name (also, she must at least have access to myIface interface definition) but, in essence, it boils down to the same issue - contract author doing the right thing.