gpt4 book ai didi

硬件管理平台-硬件产品库-反射模块

转载 作者:我是一只小鸟 更新时间:2023-08-01 22:31:26 26 4
gpt4 key购买 nike

硬件产品库-反射模块

公共项目改进

在公共项目中对当前目录进行分组,主要按照使用场景进行划分 。

按照上一章所描述的顺序进行1-4的划分,其中公共包为所有项目共用的代码,虽然该部分是编写期间随时进行编写的,但是按照个人习惯,喜欢将公共部分放到最上面.

界面布局

该项目暂不涉及酷炫页面的展示效果,因此使用的是WIndows窗体应用程序,程序名称为: HardwareGatewayProductization 。

按照上文截出的页面进行布局和控件拖拽:

  1. 窗体的大小设置:Width:1536,Heigth:1454 。

  2. 使用Panel设置布局 。

    先设置一个左右划分的布局,窗体宽度改变时左侧区域跟着改变,然后右侧再划分一个上下的,当窗体高度改变时,上册区域的高度会随之改变.

    1. 拖拽一个Panel(panel1),将Dock属性设置为Right
    2. 拖拽一个Panel(panel2)放到panel1的左侧,将Dock属性设置为Fill
    3. 拖拽一个Panel(panel3)放到panel1的内部,将Dock属性设置为Bottom
    4. 拖拽一个Panel(panel4)放到panel3的上方,将Dock属性设置为Fill

    这样子,就完成了布局设置.

  3. 在panel2中拖拽TreeView,将Dock属性设置为Fill,CheckBoxes属性为true,命名为 hardwareTV 。

  4. 在panel4中拖拽一个Label,用于展示硬件的说明信息,命名为 infoLab 。

  5. 在panel3暂时不做处理,因为该处是定时任务所需的,先不操作.

反射功能

添加 MainForm_Load 方法,一个是反射方法( InitDlls ),一个是获得反射后的类的方法( LoadLibrary ).

InitDlls

因为硬件网关项目也需要该反射方法,因此将该方法放到公共包中.

反射公共项目

注 :在公共包中创建一个AssemblyLibraries项目,创建项目时位置中添加了一个public文件夹 。

在AssemblyLibrary中创建一个control文件夹,里面创建AssemBlyControl的类.

AssemBlyControl类
  1. GetHardwareAbstracts 。

    该类的作用是通过特定文件夹获取 HardwareAbstract 类的列表,对外接口名称为 GetHardwareAbstracts 。

                                
                                  /// <summary>
    /// 通过获取的硬件路径返回硬件公共类
    /// </summary>
    /// <param name="pluginsDlls">硬件dll存放的路径</param>
    /// <returns></returns>
    public List<HardwareAbstract> GetHardwareAbstracts(string[] pluginsDlls = null)
    {
        List<HardwareAbstract> hardwareAbstracts = new List<HardwareAbstract>();
        List<string> files = GetLoadDlls(pluginsDlls);
        // 2.循环将每个dll文件都加载起来
        foreach (string dllFile in files)
        {
            HardwareAbstract hardware = GetHardwareAbstract(dllFile);
            if (hardware != null)
            {
                hardwareAbstracts.Add(hardware);
            }
        }
        return hardwareAbstracts;
    }
    
                                
                              
    • 目前HardwareAbstract只是新建的一个空类
    • GetLoadDlls方法为获取当前文件夹下面的所有dll文件
    • GetHardwareAbstract为反射获取HardwareAbstract类
  2. GetLoadDlls方法,该方法就是简单的获取特定目录下的所有dll文件,代码如下 。

                                
                                  List<string> files = new List<string>();
    if (pluginsDlls != null && pluginsDlls.Length > 0) {
        files.AddRange(Directory.GetFiles(pluginsDlls, "*.dll", SearchOption.AllDirectories));
    }
    return files;
    
                                
                              
  3. GetHardwareAbstract为核心方法 。

                                
                                  //  2.1 动态加载当前循环的dll文件
    Assembly assembly = Assembly.LoadFile(dllFile);
    //  2.2 获取当前dll中的所有的public类型
    Type[] types = null;
    try
    {
        types = assembly.GetExportedTypes();
    }
    catch (Exception ex)
    {
                    
    }
    
    //  2.3 获取IEditor接口的Type
    Type typeIEditor = typeof(HardwareAbstract);
    // 查找继承自指定接口的第一个类
    var clazz = types.FirstOrDefault(t => t.IsSubclassOf(typeof(HardwareAbstract)));
    if (clazz != null)
    {
        if (clazz.IsClass && !clazz.IsAbstract && clazz.IsPublic)
        {
            // 检查是否存在无参的构造
            if (clazz.GetConstructors().All(con => con.GetParameters().Length == 0))
            {
                HardwareAbstract hardware = Activator.CreateInstance(clazz) as HardwareAbstract;
                hardware.IncludeDll = dllFile;
                return hardware;
            }
        }
    }
    return null;
    
                                
                              

    注 :所有的硬件类都默认有无参构造函数,且因为统一,所以约定所有的项目类都无有参构造函数。如果有,则需要删除检查无法构造函数的判断.

  4. 在GetHardwareAbstract中有异常抛出,因此需要重写异常类及异常的参数 AssemblyErrorEvent 和 AssemblyErrorEventArgs 。

    • AssemblyErrorEventArgs 异常抛出时的参数信息 。

                                      
                                        public class AssemblyErrorEventArgs : EventArgs
      {
      
          /// <summary>
          /// 读取的dll文件路径
          /// </summary>
          public string DllFile { get; internal set; }
          /// <summary>
          /// 类加载失败的异常信息
          /// </summary>
          public Exception Exception { get; internal set; }
          /// <summary>
          /// 位置
          /// </summary>
          public string Seek { get; internal set; }
      }
      
                                      
                                    
    • AssemblyErrorEvent 异常类,异常类中的的参数基类为EventArgs 。

      表示反射时硬件加载出现了什么问题 。

                                      
                                        public delegate void AssemblyErrorEvent<T>(T e) where T : AssemblyErrorEventArgs;
      
                                      
                                    
InitDlls方法

添加反射公共项目依赖到硬件产品库项目中,并在InitDlls方法中添加如下代码:

                        
                          AssemblyControl assembly = new AssemblyControl();
//获得dll中的文件信息
string[] dlls = Directory.GetFiles(assembly.PluginsFolder, "*.dll", SearchOption.AllDirectories);
// 全局变量List<HardwareAbstract>
_hardwares = assembly.GetHardwareAbstracts(dlls);

                        
                      
功能延申
  1. 手动引用dll 。

    基础部分已添加成功,但是有个问题,我们将硬件的所有dll都放到同一个文件夹中,那获取的dll文件将非常多,都要进行反射效率很慢;再者例如海康的依赖包过大,对于硬件产品库提取时依赖项也需要一并提取,因此手动添加引用.

    说明 :

    为什么要这么弄,主要是所有dll都在一个文件夹中,太过于臃肿,而分开的话就要约定每个硬件项目的依赖都不要进行复制,只需要将生成路径放到产品库指定的路径(硬件类型名称+"plugins")中即可.

    而运行时需要的dll分两种,第一种为公共包中的dll,该dll只存放一份,所以项目共用;第二种为硬件项目使用,例如海康威视的依赖包。所以这两份需要分开存放,而第二种也需要根据硬件类型存放,便于后期提取时一并放到update.zip包中.

    1. 创建四个全局变量 。

      1. LocalPath:当前项目所在路径 。

      2. includeFolder:基础类引用路径,该路径存放的为公共包中的相关dll 。

      3. runtimeFolder:硬件项目特定引用的dll,可能有些没有 。

      4. pluginsFolder:组件自身的dll 。

                                            
                                              public event AssemblyErrorEvent<AssemblyErrorEventArgs> ErrorEvent;
        readonly string _includeFolder = "dlls;runtime";
        readonly string _pluginsFolder = GlobalVar.LocalPath + "plugins";
        readonly string _runtimeFolder = GlobalVar.LocalPath + "runtime";
        
                                            
                                          
    2. 在GetLoadDlls方法中直接简化为 。

                                      
                                        return new List<string>(Directory.GetFiles(_pluginsFolder, "*.dll", SearchOption.AllDirectories));
      
                                      
                                    

      此时硬件产品库的 GetHardwareAbstracts 方法就不需要传入参数了.

    3. 在 InitDlls 方法中手动添加dll的引用 。

                                      
                                        AssemblyControl assembly = new AssemblyControl();
      //引用文件夹中的dll
      string _add1Folder = string.Join(";", Directory.GetDirectories(assembly.PluginsFolder)).Replace(Application.StartupPath + "\\", "");
      string _add2Folder = string.Join(";", Directory.GetDirectories(assembly.RuntimeFolder)).Replace(Application.StartupPath + "\\", "");
      string privatePath = string.Format("{0};{1};{2}", assembly.IncludeFolder, _add1Folder, _add2Folder);
      AppDomain.CurrentDomain.AppendPrivatePath(privatePath);
      
      //获得dll中的文件信息
      _hardwares = assembly.GetHardwareAbstracts();
      
                                      
                                    
  2. 改变生成文件夹的构造 。

    vs2022默认生成时,exe和依赖的dll都在一个文件夹中,很不清晰,特别是文件很多时,特别不清晰,而修改也很简单 。

    在项目的App.config中添加配置代码,App.config全部内容如下 。

                                
                                  <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
      <runtime>
        <!--xmlns是必需的特性。指定程序集绑定所需的 XML 命名空间。 使用字符串“urn: 架构-microsoft-com:asm.v1”作为值。-->
        <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
          <!--<publisherPolicy apply="yes"/>-->
          <!--指定运行时是否使用发布者策略-->
          <!--指定加载程序集时公共语言运行时搜索的子目录, 其中privatePath是相对于*.exe.config文件的相对路径,多个文件夹以分号分隔。-->
          <probing privatePath="dlls;"/>
        </assemblyBinding>
      </runtime>
      <startup> 
          <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2" />
      </startup>
    </configuration>
    
                                
                              

下一章将介绍 LoadLibrary ,该方法主要是初始化TreeView控件,但要说明的却是 HardwareAbstract 的内容构造,因为展示TreeView简单,但是其他内容还要进行额外的添加.

最后此篇关于硬件管理平台-硬件产品库-反射模块的文章就讲到这里了,如果你想了解更多关于硬件管理平台-硬件产品库-反射模块的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com