Import property always null (MEF import issue)

2020-05-23 04:38发布

问题:

I try for some time to get things done using MEF but now, I run into a problem i need help.

Description: I have 2 DLL and one EXE file. ClassLibrary1 (LoggerImpl.cs, SomeClass.cs) ClassLibrary2 (ILogger.cs) WindowsApplicationForms1 (WindowsApplicaitonForms1.cs, Program.cs)

I need any help or direction why this doesn't work ?

// ClassLibrary1.dll
//SomeClass.cs
 public class SomeClass
    {
        [Import("Logging", typeof(ILogger))]
        public ILogger Log { get; set; } <-- ALWAYS NULL ???

        public void Print()
        {
            Log.Print();
        }

    }

// ClassLibrary1.dll
// LoggerImpl.cs
namespace ClassLibrary1
{
    [Export("Logging", typeof (ILogger))]
    public class LoggerImpl : ILogger
    {
        public void Print()
        {
            Console.WriteLine("print called");
        }
    }
}

// ClassLibrary2.dll
// ILogger.cs
namespace LogNamespace
{
    public interface ILogger
    {
        void Print();
    }
}

// WindowsFormsApplication1.exe
// WindowsFormsApplication1.cs
namespace WindowsFormsApplication1
{
    [Export("Form1",typeof(Form1))]
    public partial class Form1 : Form
    {

        [Import("Logging", typeof(ILogger))]
        public ILogger Log { set; get; }

        private CompositionContainer _container;

        public Form1()
        {
            InitializeComponent();
            Compose();
            Log.Print();

            SomeClass c = new SomeClass();
            c.Print();
        }

        private void Compose()
        {
            var catalog = new AggregateCatalog();

            catalog.Catalogs.Add(new DirectoryCatalog("."));
            catalog.Catalogs.Add(new AssemblyCatalog(System.Reflection.Assembly.GetExecutingAssembly()));
            _container = new CompositionContainer(catalog);

            try
            {
                _container.ComposeParts(this);
            }
            catch (CompositionException compositionException)
            {
                MessageBox.Show(compositionException.ToString());
            }
        }
    }
}

回答1:

If you create a new instance of a class yourself (new SomeClass()), the container won't know anything about it and won't compose it.

For a part to be composed by MEF, it needs to be created by MEF, or passed explicitly to the container. You can manually tell MEF to satisfy the SomeClass object's imports in the same way you told it to satisfy the form's imports:

SomeClass c = new SomeClass();
_container.SatisfyImports(c);
c.Print();

However, you need direct access to the container to do this, so it doesn't work as well outside of your Form1 class. In general, a better way to do it would be to export SomeClass, and create an import in your Form1 class for SomeClass:

[Export]
public class SomeClass
{
    [Import("Logging", typeof(ILogger))]
    public ILogger Log { get; set; }

    // etc.
}

public partial class Form1 : Form
{
    [Import("Logging", typeof(ILogger))]
    public ILogger Log { set; get; }

    [Import]
    SomeClass _someClass { get; set; }

    // etc.
}


回答2:

You need a statement like similar to the following to involve the SomeClass in the composition process

// ClassLibrary1.dll
//SomeClass.cs
using System;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.Windows.Forms;
using LogNamespace;

public class SomeClass
{
    [Import("Logging", typeof(ILogger))]
    public ILogger Log { get; set; } //<-- ALWAYS NULL ???

    public SomeClass()
    {
        var catalog = new AggregateCatalog();
        CompositionContainer _container;

        // catalog.Catalogs.Add(new DirectoryCatalog("."));
        catalog.Catalogs.Add(new AssemblyCatalog(System.Reflection.Assembly.GetExecutingAssembly()));
        _container = new CompositionContainer(catalog);

        _container.ComposeParts(this);
    }

    public void Print()
    {
        Log.Print();
    }

}

// ClassLibrary1.dll
// LoggerImpl.cs
namespace ClassLibrary1
{
    [Export("Logging", typeof(ILogger))]
    public class LoggerImpl : ILogger
    {
        public void Print()
        {
            Console.WriteLine("print called");
        }
    }
}

// ClassLibrary2.dll
// ILogger.cs
namespace LogNamespace
{
    public interface ILogger
    {
        void Print();
    }
}

// WindowsFormsApplication1.exe
// WindowsFormsApplication1.cs
namespace WindowsFormsApplication1
{
    [Export("Form1", typeof(Form1))]
    public partial class Form1 : Form
    {

        [Import("Logging", typeof(ILogger))]
        public ILogger Log { set; get; }

        private CompositionContainer _container;

        public Form1()
        {
            InitializeComponent();
            Compose();
            Log.Print();

            SomeClass c = new SomeClass();
            c.Print();
        }

        private void Compose()
        {
            var catalog = new AggregateCatalog();

            // catalog.Catalogs.Add(new DirectoryCatalog("."));
            catalog.Catalogs.Add(new AssemblyCatalog(System.Reflection.Assembly.GetExecutingAssembly()));
            _container = new CompositionContainer(catalog);

            try
            {
                _container.ComposeParts(this);
            }
            catch (CompositionException compositionException)
            {
                MessageBox.Show(compositionException.ToString());
            }
        }
    }
}


标签: c# mef