Can MEF be used to get the System.Type of classes marked [Export]?
Asked Answered
D

7

7

I've been successfully using MEF to obtain exported class instances. However, I came across a situation where I need to enumerate a set of exported derived classes without instantiating them. I've looked up CompositionContainer's documentation and it only seems to be able to return object instances.

I know I could have a static Type field in each derived class and export it, or do my own reflection, but I'd like to know if there's a build-in way to mark classes with the [Export] attribute and then enumerate their System.Type.

Dreiser answered 11/8, 2010 at 16:46 Comment(0)
U
4

As leppie said, there's no built in way to do this. This is by design. There's not necessarily a one-to-one mapping between exports and types (any number of parts could have property exports of type String, for example). Also, with different programming models, the part may have come from a configuration file or a dynamic programming language, so trying to get the CLR type associated with it might not make much sense.

Unswerving answered 11/8, 2010 at 21:17 Comment(1)
That's pretty much the conclusion I had come to. Thanks.Dreiser
L
4

Depending on the scope of what you are trying to do you could potentially also use System.ComponentModel.Composition.ReflectionModel.ReflectionModelServices which were API's introduced to support caching of the default catalogs. Assuming you are using the standard attributed programming model and you know all your [Export]'s are at the type level (i.e. they aren't on members) then you can call GetPartType(part) on each part in your catalog to get the type.

As Daniel pointed out if you are using other programming models then this will not work for you but if you are using only the default catalogs that come with MEF then it should do the job.

Lunt answered 11/8, 2010 at 23:52 Comment(0)
Y
4

Isn't this what you're looking for ?

    public static IEnumerable<Type> GetExportedTypes<T>()
    {
        return catalog.Parts
            .Where(part => IsPartOfType(part, typeof(T).FullName))
            .Select(part => ReflectionModelServices.GetPartType(part).Value);
    }

    private static bool IsPartOfType(ComposablePartDefinition part, string exportTypeIdentity)
    {
        return (part.ExportDefinitions.Any(
            def => def.Metadata.ContainsKey("ExportTypeIdentity") &&
                   def.Metadata["ExportTypeIdentity"].Equals(exportTypeIdentity)));
    }
Yellowknife answered 6/6, 2013 at 16:53 Comment(1)
Just added the missing method IsPartOfType, to make this work (at least for me)Slap
R
1

Is there anything wrong with using Reflection for this?

If no, that's my answer :)

Edit:

There is no builtin way to get all the types in an assembly with a certain attribute.

Requirement answered 11/8, 2010 at 16:50 Comment(1)
No, there's nothing "wrong" with using reflection for this, but as discovering [Export]'ed types is an important part of MEF, I thought it would offer support for obtaining that information.Dreiser
H
1

Typically you don't really need to select an export based on type. Instead, you can find the "correct" export based on metadata.

Have a look at the MEF programming guide section on Exports and metadata.

Handcraft answered 11/8, 2010 at 23:58 Comment(0)
C
1

This might be a bit old but I believe its good to post the correct response in here because the question comes first in Google search:

Yes you can do this thanks to Ricci Gian Maria

http://www.codewrecks.com/blog/index.php/2012/05/08/getting-the-list-of-type-associated-to-a-given-export-in-mef/

Chalybite answered 31/10, 2013 at 18:46 Comment(0)
M
1

You can treat the Export attribute as a custom attribute. I haven't test the performance when the assembly is very large.

 Type[] GetType(Assembly assembly)
 {
     return assembly.GetTypes().Where(type => Attribute.GetCustomAttribute(type, typeof(ExportAttribute)).Length > 0).ToArray();
 }
Maybellemayberry answered 19/6, 2014 at 2:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.