Свойство импорта всегда равно 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());
}
}
}
}
Ответы
Ответ 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());
}
}
}
}