2013-06-20 63 views
0

我试图我的应用程序中创建一个基本的插件插件系统,目前我在哪里建在使用我的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(); 
    } 
} 

回答

1

在.net的类型的身份是{集名称+类型名}。

因此,由于您正在使用“两个项目中都使用了相同的源文件”,这意味着2个不同的程序集(它们恰好具有相同的名称)中有2个不同的属性。因此,ether程序集将无法很容易地看到来自其他程序集的属性(两者都会看到属性,只是比较不会按照你想要的方式工作)。

解决方案:

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

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

所以往往都共享的共享类型/接口/于程序和相关组件枚举是地方到共享组装在一起。这样的程序集也可以被认为是公共API,并与设计用于与程序集成的外部组件共享。

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

+0

这么说,创建一个名为SDK或包含我的接口和属性,我需要那个名字的东西一个单独的项目,并使用该SDK作为参考这两个主要的应用程序和插件? – bizzehdee

+0

@bizzehdee - 是的。在接口等其他情况下的好处 - 如果使用源代码副本而不是程序集引用,则会遇到与您在属性中看到的完全相同的问题。 –

+0

好的,创建了sdk库,并将它链接到双方作为参考,现在一切正常,你可以编辑你的答案,让sdk参考对其他人更为清晰,并且不能接受。 – bizzehdee

相关问题