在从XAML实例化的控件中使用MEF

本文关键字:MEF 控件 XAML 实例化 在从 | 更新日期: 2023-09-27 18:19:05

我创建了一个UserControl,它使用[Import]属性导入了几个部分。

public class MyUserControl : UserControl, IPartImportsSatisfiedNotification
{
    [Import]
    public IService Service { get; set; }
    public MyUserControl()
    {
    }
    public void OnImportsSatisfied()
    {
        // Do something with Service.
    }
}

这个UserControl是从XAML实例化的,所以它的导入不满足,OnImportsSatisfied没有被调用。

<local:MyUserControl />

我的问题是如何满足我的类的导入时,它是在XAML中创建的

在从XAML实例化的控件中使用MEF

From MSDN:

要在XAML中实例化为对象元素,自定义类必须满足以下要求:
自定义类必须是公共的,并且必须公开默认的(无参数的)公共构造函数。(请参阅下面的注释部分关于结构。)
自定义类不能是嵌套类。全名路径中额外的"点"使类-名称空间划分不明确,并且干扰其他XAML特性,如附加属性。
如果一个对象可以被实例化为对象元素,则创建的对象可以填充属性元素形式的任何属性对象作为其基础类型。
您仍然可以提供对象值对于不满足这些条件的类型,如果启用值转换器。有关详细信息,请参见类型转换器和标记XAML.

从这里,您有两个选择:
1)使用TypeConverter:
使用类型转换器可以在没有无参数构造函数的情况下实例化对象,但是必须提供一个TypeConverter来进行实例化。

现在,我从来没有使用过它,我不能进一步帮助你。

2)使用ServiceLocator检索IService:
public class MyUserControl : UserControl
{    
    public IService Service { get; set; }
    public MyUserControl()
    {
       Service = Microsoft.Practices.ServiceLocation.ServiceLocator.Current.GetInstance<IService>();
       // You can do something with Service here already.
    }
}

我知道这是你课堂设计的一个变化,但希望你能应付它。

希望有帮助,

巴布。

如果你不想让mef创建你的usercontrol,你必须在你的usercontrol中使用compostioncontainer并直接调用GetExport。但是,你有问题得到你的组合容器的实例:)

ps:我允许我在我的应用程序中创建我的WPF视图

(我再次提到这个,以防有人遇到它。作为免责声明,我不是专家,这些只是我发现有效的解决方案。

我发现调用CompositionContainer.ComposeParts(myUserControl)工作。我在控件的构造函数中调用它。您需要以某种方式获得对CompositionContainer的引用:

public MyUserControl()
{
    compositionContainer.ComposeParts(this);
}

其他解决方案:

这可能是不必要的,但这里有另一种方法。这要复杂得多,但它确实允许您在XAML中"Import"您的用户控件。

要满足您的导入,需要导出MyUserControl,然后由MEF实例化。我的解决方案是在包含"Locator"对象的类中使用静态字段。这个Locator对象负责导入和返回导出的对象。然后我可以在XAML中引用这个静态字段,如下所示:

<ContentControl Content="{Binding MyUserControl, Source={x:Static v:SomeClass.Locator}}">

SomeClass有一个称为Locator的静态属性,该属性在应用程序生命周期的早期被分配。然后定位器可以有一个MyUserControl属性来获取Import


(免责声明:下面的链接是我自己的框架和解决方案,因为它是粗糙的,如果使用应该小心使用)

为提供上述示例,我将解释如何在我的框架中实现它:

在我的例子中,SomeClassSystem.Windows.Application的子类,它取代了App.xaml, ViewLocator是在它的OnStartup上分配的,如图所示。

ViewLocator类是导入视图的System.Dynamic.DynamicObject,它有一个自定义的ViewExport属性。视图使用ViewExportAttribute.Alias属性进行标识。

这是一个视图被导出并被分配别名的例子。

最后,视图的MEF实例化实例可以在XAML中使用如下:

<ContentControl Content="{Binding HomeView, Source={x:Static v:FrameworkApp.ViewLocator}}">