首页 > 开发 > .Net > 正文

用 .NET 实现插件机制

2020-02-03 16:00:54
字体:
来源:转载
供稿:网友
  • 本文来源于网页设计爱好者web开发社区http://www.html.org.cn收集整理,欢迎访问。
  •   .net 提供的反射(reflection)机制可以很方便的加载插件。本文提供一种方法,可以灵活的正确的载入所需的插件。

    在.net中,一个完整的类型名称的格式如 "类型名, 程序集名"。

    例如:"system.configuration.namevaluesectionhandler, system, version=1.0.3300.0, culture=neutral, publickeytoken=b77a5c561934e089"。

    • 类型名为:system.configuration.namevaluesectionhandler,这是带名字空间的完整类型名。
      你也可以使用该类型的fullname得到。
      如:string typename = typeof(namevaluesectionhandler).fullname;
    • 程序集名为:"system, version=1.0.3300.0, culture=neutral, publickeytoken=b77a5c561934e089",
      程序集名为system,系统为自动为其适配扩展名(如system.dll或system.exe);
      version、culture、publickeytoken为程序集的具体版本、文化背景、签名,没有特定要求,这些都可以省略。

    我们可以根据类型的名称,来动态载入一个所需要的类型。如:

    string typename = "system.configuration.namevaluesectionhandler, system";
    type t = type.gettype(typename);
    object obj = activator.createinstance(t);

    system.configuration.namevaluesectionhandler obj = (system.configuration.namevaluesectionhandler)activator.createinstance(t);

    此时,obj 就是所需要的类型实例。

    通常的插件,是需要实现一定的接口的类。因此,在载入插件之前,需要确定该插件类型是否是合适的。
    比如,一个插件的接口为 iplugin,那么我们可以用如下方式来识别:

    string interfacename = typeof(iplugin).fullname;
    string typename = "muf.myplugin, myplugin";
    type t = type.gettype(typename);
                 
    if (  t == null
      || !t.isclass
      || !t.ispublic
      ||  t.getinterface(interfacename) == null)
    {
     return null; // 不是所需要的插件
    }

    总结上述代码,我们可以做出通用的加载插件的代码:

    /// <summary>
    /// 动态装载并创建类型,该类型拥有指定接口
    /// </summary>
    /// <param name="classname">类型名称</param>
    /// <param name="interfacename">指定的接口名称</param>
    /// <param name="param">指定构造函数的参数(null或空的数组表示调用默认构造函数)</param>
    /// <returns>返回所创建的类型(null表示该类型无法创建或找不到)</returns>
    public static object loadobject(string classname, string interfacename, object[] param)
    {
     try
     {
      type t = type.gettype(classname);
                 
      if ( t == null
       || !t.isclass
       ||  !t.ispublic
       ||  t.isabstract
       ||  t.getinterface(interfacename) == null)
      {
       return null;
      }

      object o = activator.createinstance(t, param);
      if( o == null )
      {
       return null;
      }
        
      return o;
     }
     catch( exception ex )
     {
      return null;
     }
    }

    以后,我们就可以使用loadobject载入任何所需的插件。

    插件配置,一般有两种方法:
    1. 将插件类型名称写在配置文件中,如app.config。配置文件的使用可以参考沐枫专栏的其它文章。
    2. 指定一个目录为插件目录,然后在该目录中所有的程序集(如*.dll)全部加载,并用反射机制,获取所有的公共类型,并全部尝试用loadobject加载,加载成功的就是合适的插件。


    发表评论 共有条评论
    用户名: 密码:
    验证码: 匿名发表