首先,让 Program 导入一个计算器。 这样就可以将用户界面问题(例如,将传递给 Program 的控制台输入和输出)与计算器的逻辑相分离。
将下面的代码添加到 Program 类中:
[Import(typeof(ICalculator))]
public ICalculator calculator;
请注意,虽然 calculator 对象的声明并没有特别之处,但该对象使用 ImportAttribute 特性进行了修饰。此特性将某个对象声明为一个导入;也就是说,在组合对象时将由组合引擎对它进行填充。
每个导入都有一个协定,用于确定将与之匹配的导出。协定可以是显式指定的字符串,也可以由 MEF 从给定的类型(在此例中为 ICalculator 接口)自动生成。使用匹配的协定声明的任何导出都将满足此导入。请注意,尽管 calculator 对象的类型实际为 ICalculator,但这并不是必需的。协定与导入对象的类型无关。(在此例中,您可以忽略 typeof(ICalculator)。MEF 将会自动假定协定基于导入的类型,除非您显式指定协定将基于的类型。)
将这个非常简单的接口添加到模块或 SimpleCalculator 命名空间中:
public interface ICalculator
{
String Calculate(String input);
}
既然您已定义 ICalculator,就需要一个类来实现它。将下面的类添加到模块或 SimpleCalculator 命名空间中:
[Export(typeof(ICalculator))]
class MySimpleCalculator : ICalculator
{
}
此处是将与 Program 中的导入匹配的导出。为了使导出与导入匹配,导出必须具有相同的协定。依据基于 typeof(MySimpleCalculator) 的协定进行导出时会造成不匹配,将不会填充导入;协定需要完全匹配。
因为组合容器将由此程序集中提供的所有部件进行填充,所以 MySimpleCalculator 部件将可用。当 Program 的构造函数对 Program 对象执行组合操作时,此对象的导入将由特意创建的 MySimpleCalculator 对象填充。
用户界面层 (Program) 不需要知道任何其他内容。因此,您可以通过 Main 方法来填充用户界面逻辑的其余部分。
将以下代码添加到 Main 方法中:
static void Main(string[] args)
{
Program p = new Program(); //Composition is performed in the constructor
String s;
Console.WriteLine("Enter Command:");
while (true)
{
s = Console.ReadLine();
Console.WriteLine(p.calculator.Calculate(s));
}
}
此代码只是读取一行输入,并对结果调用 ICalculator 的 Calculate 函数,该函数将结果写回到控制台。这就是 Program 中所需的全部代码。剩下的所有工作将在部件中完成。