无法跨程序集通过自定义属性获取类型

本文关键字:自定义属性 获取 取类型 程序集 | 更新日期: 2023-09-27 18:19:13

我试图在我的应用程序中创建一个基本的小部件插件系统,我目前处于一个症结所在,内置的小部件使用我的WidgetAttribute属性类(编译成exe)工作良好,但我似乎无法在我编写的任何测试插件中找到任何小部件。

我使用以下代码来加载程序集:

    public static void LoadAll()
    {
        String[] m_filenames = Directory.GetFiles("plugins", "*.dll", SearchOption.TopDirectoryOnly);
        foreach (String fn in m_filenames)
        {
            Load(Directory.GetCurrentDirectory() + "''" + fn);
        }
    }
    public static void Load(String filename)
    {
        Assembly m_asm = Assembly.Load(File.ReadAllBytes(filename));
        PluginAssemblies.Add(m_asm);
    }

,然后使用下面的代码来获取所有具有my属性(表示小部件及其元数据)的类型:

    public static void LoadAllWidgets()
    {
        foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
        {
            LoadAllWidgets(assembly);
        }
        foreach (Assembly assembly in PluginLoader.PluginAssemblies)
        {
            LoadAllWidgets(assembly);
        }
    }
    public static void LoadAllWidgets(Assembly asm)
    {
        foreach (Type type in asm.GetTypes())
        {
            WidgetAttribute[] m_attribs = (WidgetAttribute[])type.GetCustomAttributes(false).OfType<WidgetAttribute>().ToArray();
            if (m_attribs.Length > 0)
            {
                WidgetsByGuid.Add(m_attribs[0].ID, type);
                WidgetNamesByGuid.Add(m_attribs[0].ID, m_attribs[0].Name);
                WidgetShowInMenuByGuid.Add(m_attribs[0].ID, m_attribs[0].ShowInMenu);
            }
        }
    }

当我调用LoadAllWidgets第二次(即。加载来自其他程序集的小部件),我在类型数组中获得类型,但是GetCustomAttributes返回一个空数组。

属性定义如下,两个项目使用相同的源文件:

using System;
using System.Reflection; 
namespace WSW.Classes
{
[AttributeUsage(AttributeTargets.Class)]
public class WidgetAttribute : System.Attribute
{
    public String Name { get; set; }
    public Guid ID { get; set; }
    public Boolean ShowInMenu { get; set; }
    public WidgetAttribute(String guid, String name, Boolean showmenu)
    {
        Name = name;
        ID = Guid.Parse(guid);
        ShowInMenu = showmenu;
    }
    public WidgetAttribute(String guid, String name)
    {
        Name = name;
        ID = Guid.Parse(guid);
        ShowInMenu = true;
    }
}
}

谁能告诉我为什么我不能从我的程序集之外的类型获得自定义属性,即使我已经加载了它,可以看到类型?

EDIT另一个程序集中的插件类定义如下:

[WSW.Classes.WidgetAttribute("{42544B13-7353-40FD-B1D8-DA46A247110A}", "Testimonials")]
public partial class Testimonials : UserControl
{
    public Testimonials()
    {
        InitializeComponent();
    }
}

无法跨程序集通过自定义属性获取类型

. net中类型的标识为{程序集名称+类型名称}。

所以,既然你使用"在两个项目中使用相同的源文件"这意味着在2个不同的程序集中有2个不同的属性(恰好具有相同的名称)。因此,两个程序集将无法轻松地看到另一个程序集的属性(两个程序集都可以看到属性,只是比较将无法按您想要的方式工作)。

解决方案:

  • 确保每个共享属性只被编译成一个程序集,并且该属性的所有消费者都使用该程序集。
  • 比较属性名,而不是类型。

当使用类型标识时,同样的考虑也适用于其他情况。例如,如果接口在两个程序集之间作为源副本共享,那么这些接口和实现它们的类将不被认为是兼容的。

因此,通常所有共享的共享类型/接口/枚举用于程序和相关程序集的地方都放到了共享程序集中。这样的程序集也可以被视为公共API,并与设计用于与程序集成的外部组件共享。

请注意,一旦您与其他人共享程序集,这意味着您需要版本控制,因为对共享程序集的许多更改(例如,重命名类型/方法)将导致依赖程序集无法加载或故障。