【发布时间】:2012-11-05 08:38:34
【问题描述】:
我正在尝试了解 MEF 并对此做了一些示例。但是,当我尝试执行下面的特定代码时,我遇到了一个例外。
ConsoleApplication2.program
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.Reflection;
namespace ConsoleApplication2
{
class Program
{
[Import(typeof(Contracts.IInput))]
public Contracts.IInput myinterface { get; set; }
public void Method()
{
var catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
var container = new CompositionContainer(catalog);
container.ComposeParts(container );
Console.WriteLine(myinterface.IsValid());
}
public static void Main(string[] args)
{
var obj = new Program();
obj.Method();
Console.ReadLine();
}
}
}
我有一个单独的项目来定义接口。
namespace Contracts
{
public interface IInput
{
//All classes that inherit IInput must implement the IsValid Property.
string IsValid();
}
}
在另一个单独的项目中,我使用了一个导出类。
using System.ComponentModel.Composition;
using Contracts;
namespace Plugin
{
[Export(typeof(Contracts.IInput))]
public class Plugin : IInput
{
public string IsValid()
{
return "1";
}
}
}
现在,所有这些都在同一个“bin\Debug”文件夹中生成(两个库文件和一个可执行文件)。但是在到达代码时执行,“composeParts(this)”出现如下异常,
Object reference not set to an instance of an object.
当我尝试更改“Composeparts(container)”时,出现另一个异常,如下所示,
**> 合成产生了单个合成错误。根本原因是
提供如下。查看 CompositionException.Errors 属性 更详细的信息。
1) 无法填充集合 'ConsoleApplication2.Program.myinterface' 因为它没有 实现 ICollection 或者是只读的。如果集合不是 IEnumerable 或 T[] 它必须实现 ICollection 并且是 使用默认构造函数预初始化或可写。
导致:无法激活部件“ConsoleApplication2.Program” 元素:ConsoleApplication2.Program --> ConsoleApplication2.Program **
- 你能告诉我哪里出错了吗?
- 我认为 composeparts(this) 和 composeparts(container) 都是相同的,因为我使用的是 Assembly.GetExecutingAssembly()。如果是这样,那为什么会抛出两个不同的异常?
我用过 importmany 之类的
class Program
{
[ImportMany(typeof(Contracts.IInput))]
public IEnumerable<Contracts.IInput> myinterface { get; set; }
public void Method()
{
var catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
var container = new CompositionContainer(catalog);
try
{
container.ComposeParts(container);
foreach (var i in myinterface)
Console.WriteLine(i.IsValid());
}
catch (CompositionException compositionException)
{
Console.WriteLine(compositionException.ToString());
}
}
但在这种情况下,myinterface 仍然为 null,这会引发 null 引用异常。
【问题讨论】:
-
按照 Blachshma 的方式,只需将 assemblycatalog 更改为 DirectoryCatalog,这个例子就可以了!
-
感谢 Blachshma 的额外回答。如果我对他的理解正确,那么这些就是这里的要点: 1. import 语句只有在 Constructor 完成运行后才会发挥作用。 2. 所以不要对构造函数中的属性使用 import 语句。希望这可以帮助。 3. 目录目录在指定目录中查找满足import语句的dll。 4. 此外,程序集目录在可执行文件的项目中搜索满足导入语句的任何类/属性。
标签: c# visual-studio-2010 .net-4.0 mef