如何从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
相关产品推荐
相关产品推荐

