You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从XAML创建的控件获取其创建方程序集?(Avalonia/WPF)

获取创建MyControl的插件程序集(Avalonia/WPF通用)

问题场景

  • 程序集A定义MyControl
  • 动态加载的插件程序集B引用A,通过XAML或DataTemplate创建MyControl实例
  • 在MyControl构造函数中调用Assembly.GetCallingAssembly()只能拿到WPF/Avalonia框架内部程序集,无法获取插件程序集B
  • 需获取B的引用以对接对应版本的插件逻辑

可行解决方案

1. 附加属性传递程序集信息

在程序集A中定义附加属性,让插件B在XAML中显式传递自身程序集引用:

// 程序集A中的代码
public static class AssemblyContext
{
    public static readonly AttachedProperty<Assembly> AssemblyProperty =
        AvaloniaProperty.RegisterAttached<AssemblyContext, Control, Assembly>("Assembly");

    public static void SetAssembly(Control element, Assembly value)
    {
        element.SetValue(AssemblyProperty, value);
    }

    public static Assembly GetAssembly(Control element)
    {
        return element.GetValue(AssemblyProperty);
    }
}

在插件B的XAML中为MyControl赋值:

<!-- 程序集B的XAML -->
<local:MyControl local:AssemblyContext.Assembly="{x:Static assembly:Assembly.GetExecutingAssembly()}" />

在MyControl中读取该属性:

public MyControl()
{
    InitializeComponent();
    Loaded += (s, e) =>
    {
        var pluginAssembly = AssemblyContext.GetAssembly(this);
        // 基于pluginAssembly对接对应版本插件逻辑
    };
}

2. 从DataTemplate关联的资源上下文获取

如果MyControl通过B中定义的DataTemplate创建,可在B的资源字典中注入程序集引用,再从视觉树资源中查找:

<!-- 程序集B的资源字典 -->
<ResourceDictionary>
    <Assembly x:Key="PluginAssembly" Source="{x:Static assembly:Assembly.GetExecutingAssembly()}" />
    <DataTemplate DataType="{x:Type local:MyViewModel}">
        <local:MyControl />
    </DataTemplate>
</ResourceDictionary>

在MyControl的Loaded事件中读取资源:

public MyControl()
{
    InitializeComponent();
    Loaded += (s, e) =>
    {
        if (TryFindResource("PluginAssembly", out var resource) && resource is Assembly pluginAssembly)
        {
            // 使用pluginAssembly处理逻辑
        }
    };
}

3. 遍历视觉树查找插件类型实例

如果MyControl的视觉树中存在B定义的类型(如MyFrame),可通过遍历视觉树找到该实例并获取其程序集:

public static T FindVisualParent<T>(DependencyObject child) where T : DependencyObject
{
    var parent = VisualTreeHelper.GetParent(child);
    if (parent == null) return null;
    return parent is T t ? t : FindVisualParent<T>(parent);
}

// 在MyControl中调用
Loaded += (s, e) =>
{
    var myFrame = FindVisualParent<MyFrame>(this);
    if (myFrame != null)
    {
        var pluginAssembly = myFrame.GetType().Assembly;
        // 对接插件逻辑
    }
};

4. 基于AssemblyLoadContext的关联查询

如果插件B在独立的AssemblyLoadContext中加载,可通过MyControl的程序集上下文,查询该上下文中的插件程序集:

var currentAlc = AssemblyLoadContext.GetLoadContext(typeof(MyControl).Assembly);
// 按插件程序集命名规则筛选,例如前缀为"Plugin."
var pluginAssembly = currentAlc.Assemblies.FirstOrDefault(a => a.GetName().Name.StartsWith("Plugin."));

内容的提问来源于stack exchange,提问作者cboittin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 21:17:48