繁体   English   中英

属性,接口或抽象类

[英]Attribute, interface, or abstract class

我想知道以下实现的一般建议(属性,接口,抽象类或其组合):

    /// <summary>
    /// Loads class specific information into a list for serialization. The class must extend PlugIn.
    /// The filenames parameter is passed from a FileDialog.
    /// </summary>
    /// <param name="filenames">Accepts any number of filenames with fully qualified paths.</param>
    public static void ExtractPlugInData(params string[] filenames)
    {
     List<Type> l;

     foreach (string f in filenames)
     {
     Assembly a = Assembly.LoadFrom(f);
     // lambda expression selects any class within a library extending the abstract PlugIn class
     l = a.GetTypes().Where(type => typeof(PlugIn).IsAssignableFrom(type)).ToList<Type>();

     if (l.Count > 0)
            //  write data to serializable class
      WritePlugInData(f , l);
     else
      // throw exception
      WriteLine("{0} :: No PlugIn Data Found" , a.FullName);
            }
    }

我意识到每种方法都有优点和缺点。 显然,属性需要一些反思(抽象扩展和接口实现也是如此)。 抽象类采用我们唯一的基本继承,接口中的任何未来更改都可以破坏任何现有插件。 所以,正如我所看到的那样,这些都是缺点。

性能不是问题(除非有一些我看不到的东西)因为任何反射只在提取限定类时才进行一次。 要保存的关键数据是插件的名称(“MyPlugIn”),命名空间(“SuperPlugIn.PlugInClass”)以及.dll的启动路径。 现在,使用抽象的PlugIn类,强制执行属性的扩展。 如果我们实现接口(IPlugIn),这或多或少是相同的结果。

我们允许最终用户编写自定义插件。 使用我们内部编写的插件,可以很容易地为我们的应用程序教授和实施一个必需的结构来实例化一个合格的类。 但是,如果出现重大变化,我也在考虑最终用户的困难或不便。

欢迎所有评论,建议和问题!

注意:感谢Jon Skeet在片段中的lambda表达式。 :)

编辑:我应该在开始时注意到这是平台无关的(即Mono)。

更新:基于下面的优秀建议,评论和链接,混合属性和接口是最好的方法。 通过属性,您可以加载程序集并相当安全地检查所需的信息和实现,而无需实例化插件类/对象。 这在允许第三方或最终用户创建自定义插件的情况下非常理想。 我们可以检查以确保正确的合同实施到位,其中属性表示它是假设的。 我们可以检查所需的依赖项和资源,并在实例化之前提醒开发人员任何问题。

您希望最终用户编写插件吗? 除非你的最终用户是程序员,否则我认为这不是一个好主意。

这次我会保持我的答案很短,因为这是一个相当 大的 honkin' 欺骗

编辑:对于Mono,请查看Mono.Addins

Assembly.GetTypes是一个非常昂贵的调用,我会尽可能避免它。 (App启动时间很重要)

更快的方法是(我没有基准测试)一个程序集级属性,可以像这样使用:

[assembly: PluginClass(typeof(MyPlugin), more info)]

然后,您可以在Assembly上调用GetCustomAttributes ,这可能比GetTypes快得多。

使用LINQ:

filenames.SelectMany(f => 
        Assembly.LoadFrom(f).GetCustomAttributes(typeof(PluginClassAttribute), true)
        .Cast<PluginClassAttribute>()
        .Select(a => a.PluginType)
).ToList();

我可能倾向于使用属性。 使用元数据扩展基类系统正是它们的目的,并且说“这个类是一个插件”当然适合这个法案。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM