Being selective with Imports

May 16, 2009 at 11:11 PM

Hi,

I have a set of Exports which provide functionality across the entire application. However, in one part of the application I only want it to be deal with a certain type of Export. I know I can add MetaData and do some dynamic filtering on the export object and the underlying dictionary - however I don't really want this bleeding into my codebase every time I want this subset.  What I wanted to be able to do is have this logic hidden away so that my Import can somehow only be populated with the selected Exports.

For example:

        [Import("Filter", typeof(ILogger))]
        public LoggerFilter LoggerWithFilter { get; set; }

And I could use it via if (LoggerWithFilter != null) LoggerWithFilter.Value.Write("This is a test");  (Getting the Logger via Value - still not ideal!)

I came up with this. Using the Preview 5 Action export, I could have a validator.

    public class LoggerValidator
    {
        [Export("Filter", typeof(ValidatorDelegate<ILogger>))]
        public bool UseThisLogger(ILogger logger)
        {
            logger.Write("I've been asked to validate.... ");
            return true;
        }
    }

I then had a filter which would populate my Imports...

    [Export("Filter", typeof(ILogger))]
    public class LoggerFilter
    {
        private readonly ValidatorDelegate<ILogger> _logValidator;
        [Import]
        private IEnumerable<ILogger> Loggers;

        public ILogger Value
        {
            get
            {
                foreach (ILogger logger in Loggers)
                    if (_logValidator(logger))
                        return logger;

                return null;
            }
        }

        [ImportingConstructor]
        public LoggerFilter([Import("Filter")]ValidatorDelegate<ILogger> logValidator)
        {
            _logValidator = logValidator;
        }
    }

 

Two major problems.

1) I still can't dynamically control how my LoggerValidator object behaves and how it selects which loggers to use.

2) It feels overally complex and a little messy!

What is a better way of being able to filter down which Exports are selected?

Hope this makes sense...

Thanks

Ben Hall

May 16, 2009 at 11:14 PM

After posting this I realised there might be. I could add a contract name to my import when I want to be selective.

    [Import("Filtered", typeof(ILogger))]
    public ILogger FilteredLogger { get; set; }

Then any export which falls under this category has adds the additional contract attribute.

    [Export(typeof(ILogger))]
    [Export("Filtered", typeof(ILogger))]
    public class Logger : ILogger

It is a lot cleaner than the above approach. But its still all done at compile time. Is there any way I can be more dynamic about this?

Thanks

Ben