Подтвердить что ты не робот

Свойство импорта всегда равно null (проблема импорта MEF)

Я пытаюсь в течение некоторого времени сделать что-то с помощью MEF, но теперь я столкнулся с проблемой, мне нужна помощь.

Описание: У меня есть 2 DLL и один EXE файл. ClassLibrary1 (LoggerImpl.cs, SomeClass.cs) КлассLibrary2 (ILogger.cs) WindowsApplicationForms1 (WindowsApplicaitonForms1.cs, Program.cs)

Мне нужна помощь или руководство, почему это не работает?

// 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());
            }
        }
    }
}
4b9b3361

Ответ 1

Если вы создаете новый экземпляр класса самостоятельно (новый SomeClass()), контейнер ничего не знает об этом и не будет его компилировать.

Чтобы часть была составлена ​​MEF, она должна быть создана MEF или передана явно контейнеру. Вы можете вручную сказать MEF, чтобы удовлетворить импорт объектов SomeClass так же, как вы сказали ему, чтобы удовлетворить импорт форм:

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

Однако для этого вам нужен прямой доступ к контейнеру, поэтому он не работает также вне вашего класса Form1. В общем, лучшим способом сделать это будет экспорт SomeClass и создание импорта в вашем классе Form1 для 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

Вам понадобится инструкция, подобная приведенной ниже, чтобы задействовать SomeClass в процессе композиции

// 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());
            }
        }
    }
}