문제

I'm trying to build an application that uses the Managed Entity Framework to import a unknown number of classes and their related methods.

For example I have the following 2 classes:

interface IClass { }

[Export(typeof(IClass))]
class Class1 : IClass
{
    [Export(typeof(Func<int>))]        
    public int GetNumber()
    {
        return 1;
    }
}

[Export(typeof(IClass))]
class Class2 : IClass
{
    [Export(typeof(Func<int>))]
    public int GetNumber1()
    {
        return 1;
    }

    [Export(typeof(Func<int>))]
    public int GetNumber2()
    {
        return 2;
    }
}

Class1 has a single GetNumber method, whilst Class2 has two.

In my program I am able to create imports that load the classes and methods.

class Program
{   
    [ImportMany]
    IEnumerable<IClass> Classes { get; set; }

    [ImportMany(typeof(Func<int>))]
    IEnumerable<Func<int>> Methods { get; set; }

    static void Main(string[] args)
    {
        Program p = new Program();
        p.Run();
        Console.Read();
    }

    void Run()
    {
        AssemblyCatalog catalog = new AssemblyCatalog(System.Reflection.Assembly.GetExecutingAssembly());
        CompositionContainer container = new CompositionContainer(catalog);

        container.ComposeParts(this);

        if(this.Classes.Count() != 2)
        {
            throw new InvalidOperationException();
        }

        this.Methods.ToList().ForEach(m => Console.WriteLine(m()));
    }
}

Output

  • 1
  • 1
  • 2

The problem I have is that link between class and method has been lost. As all classes and methods are thrown into the same IEnumerable, I can't tell which class was linked to which method.

I really want to build an in memory structure similar which models the hierarchy of class and method, e.g.

Class1: GetNumber

Class2: GetNumber1, GetNumber2

How can I import these same classes and method but retain the class to method link?

도움이 되었습니까?

해결책

This is achievable by using container.GetExportedValues, this will expose the the classes and methods. They can then be grouped up and composed into the preferred structure. You don't actually need the [ImportMany] at all. This feels a little backwards, given MEF is meant to be performing the composition for you, but it works in this case.

class Program
{
    static void Main(string[] args)
    {
        Program p = new Program();
        p.Run();
        Console.Read();
    }

    void Run()
    {
        AssemblyCatalog catalog = new AssemblyCatalog(System.Reflection.Assembly.GetExecutingAssembly());
        CompositionContainer container = new CompositionContainer(catalog);

        Dictionary<IClass, List<Func<int>>> dictionary = new Dictionary<IClass, List<Func<int>>>();

        IEnumerable<IClass> classes = container.GetExportedValues<IClass>();
        IEnumerable<Func<int>> methods = container.GetExportedValues<Func<int>>();

        foreach(var c in classes)
        {
            dictionary[c] = new List<Func<int>>();
        }

        foreach(var m in methods)
        {
            dictionary[(IClass)m.Target].Add(m);
        }            

        foreach(var kvp in dictionary)
        {
            kvp.Value.ForEach(m => Console.WriteLine(m()));
        }
    }
}

If you need the metadata use container.GetExports.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top