2

我正在尝试在我的应用程序中创建一个基本的小部件插件系统,我目前正处于一个关键点,即使用我的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);
    }

然后使用以下代码获取所有具有我的属性的类型,该属性表示一个小部件及其元数据:

    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();
    }
}
4

1 回答 1

3

.Net 中类型的标识是 {Assembly Name + type name}。

因此,由于您使用“两个项目中使用相同的源文件”,这意味着 2 个不同的程序集中有 2 个不同的属性(它们恰好具有相同的名称)。因此,以太程序集将无法轻松查看另一个程序集的属性(两者都会看到属性,只是比较不会按照您想要的方式工作)。

解决方案:

  • 确保每个共享属性仅编译为一个程序集,并且该程序集由该属性的所有使用者使用。
  • 比较属性的名称,而不是类型。

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

因此,程序和相关程序集的所有共享共享类型/接口/枚举通常都放在共享程序集中。此类程序集也可以视为公共 API,并与旨在与您的程序集成的外部组件共享。

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

于 2013-06-20T23:00:29.793 回答