首页 > 其他分享 >硬件管理平台-硬件产品库-反射模块

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

时间:2023-08-01 18:45:21浏览次数:47  
标签:assembly string HardwareAbstract 产品库 dll 硬件 模块 public

硬件产品库-反射模块

公共项目改进

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

按照上一章所描述的顺序进行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中有异常抛出,因此需要重写异常类及异常的参数AssemblyErrorEventAssemblyErrorEventArgs

    • 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简单,但是其他内容还要进行额外的添加。

标签:assembly,string,HardwareAbstract,产品库,dll,硬件,模块,public
From: https://www.cnblogs.com/wanghun315/p/17598776.html

相关文章

  • C#+WPF上位机开发(模块化+反应式)
    在上位机开发领域中,C#与C++两种语言是应用最多的两种开发语言,在C++语言中,与之搭配的前端框架通常以QT最为常用,而C#语言中,与之搭配的前端框架是Winform和WPF两种框架。今天我们主要讨论一下C#和WPF这一对组合在上位机开发过程中的实际应用。一、模块化概念开发一套完善的软件,离不开......
  • python如何制作自己的模块
    你可以按照以下步骤制作自己的Python模块:1.创建一个新的.py文件,并定义你自己的函数或类。2.编写文档字符串docstring,说明该函数或类的作用、参数和返回值说明等。3.给你的函数或类添加恰当的注释。4.将该.py文件放在工程目录的一个新文件夹中,这个文件夹就是你的模块。5.在你......
  • python如何制作自己的模块
    你可以按照以下步骤制作自己的Python模块:1.创建一个新的.py文件,并定义你自己的函数或类。2.编写文档字符串docstring,说明该函数或类的作用、参数和返回值说明等。3.给你的函数或类添加恰当的注释。4.将该.py文件放在工程目录的一个新文件夹中,这个文件夹就是你的模块。5.在你......
  • 硬件管理平台-搭建
    硬件管理平台-搭建简述之前描述了硬件网关的公共部分的搭建方式,本次回归到硬件管理平台,进行下一步的开发工作。在开始之前,想先描述下文章后续的思路,该平台涉及了多个项目,来回跳跃式的叙述估计到最后谁也无法看懂了,如果不跳跃,当作伏笔去写,最后伏笔就变成了坑,怕填不完。因此在这......
  • RTSP流媒体服务器LntonNVR(源码版)平台硬件设备拔电关闭后不能自动重启的问题解决方案
    LntonNVR视频边缘计算网关可以放置在项目现场,7x24小时不间断使用,通电联网即可成功运行,部署操作十分简单。我们在测试时,将LntonNVR注册到服务启动,拔掉硬件设备的电源后,再次恢复供电,发现LntonNVR服务并没有再次启动。对此我们也进行了分析与排查。排查步骤如下:1、首先检查是否已经......
  • Python-8-Python模块
    8-1Pycharm安装 http://www.jetbrains.com/pycharm/选Download下载,下载Community社区版本,此时就已经在下载了。安装过程中勾选"64-bitlauncher","AddlauncherdirtoPATH",".py".首次启动,不安装插件,直接启动。需要添加python解释器,设置字体。8-2介绍Python项目组织......
  • DC电源模块输出电压的调节范围
    BOSHIDADC电源模块输出电压的调节范围DC电源模块是一种可以将交流电转换为直流电的设备,可以广泛应用于电子、通信、工业自动化等领域。在实际使用中,输出电压的调节范围非常重要,因为它决定了该模块能够适应的电器设备的种类和使用范围。下面将详细介绍DC电源模块输出电压的调节范......
  • 【Python】calendar_标准库的日历模块
    日历模块calendar.calendar(year,c,w,l)c:每月间隔距离w:每日宽度间隔l:每星期行数打印年日历#coding:utf-8importcalendarfromloguruimportloggeraslogsif__name__=="__main__":"""Run""""""打印年日历......
  • pandas模块--------------------------------相同(不同)文件夹下相同格式的Excel表格数
    上代码:importpandasaspdimportos#文件路径file_dir=r'C:/Users/Administrator/Desktop/test/'#构建新的表格名称new_filename=file_dir+'/new_file.xlsx'#找到文件路径下的所有表格名称,返回列表file_list=os.listdir(file_dir)new_list=[]forfileinfile_list:......
  • 20 re/collection/time/random模块
    re模块补充说明importreret=re.findall('a(b)c','abcabcabcabc')#优先显示括号内东西print(ret)#['b','b','b','b']ret=re.findall('a(?:b)c','abcabcabcabc')#?:表示忽视括号print(r......