【从零开始入门unity游戏开发之——C#篇39】C#反射使用——Type 类、Assembly 类、Activator 类操作程序集

news2025/1/3 3:04:38

文章目录

  • 前言
  • 一、前置知识
    • 1、编译器
    • 2、程序集(`Assembly`)
    • 3、元数据(`Metadata`)
  • 二、反射
    • 1、反射的概念
    • 2、反射的作用
    • 3、反射的核心`Type` 类
      • 3.1 `Type` 类介绍
      • 3.2 不同方法获取 `Type`
      • 3.3 获取type类型所在的程序集的相关信息
    • 4、反射的常见用法
      • 4.1 获取 `Type`类型信息
      • 4.2 获取类的公共成员
      • 4.3 获取类的构造函数
      • 4.4 获取类的字段
      • 4.5 获取类的成员方法
      • 4.6 其他反射操作
    • 5、反射访问并操作私有(private)成员(包括字段、属性、方法等)
    • 6、总结
  • 三、关键类Assembly和Activator
    • 1、**反射中的关键类**
      • 1.1 `Type` 类(前面已经介绍过了)
      • 1.2 `Assembly` 类
      • 1.3 `Activator` 类
    • 2、**使用 `Activator` 类实例化对象**
      • 示例 1:无参构造函数
      • 示例 2:带参数的构造函数
    • 3、**使用 `Assembly` 类加载程序集**
      • 3.1 加载程序集:
        • (1)获取当前执行的程序集:
        • (2)从指定路径加载程序集:
      • 3.2 获取指定名称的类型
      • 3.3 获取所有类型:
      • 3.4 获取并调用类型中的方法:
    • 4、综合示例
  • 四、**总结**
  • 专栏推荐
  • 完结

前言

C# 反射 (Reflection) 是一种强大的机制,它允许程序在运行时动态地查看和操作程序的元数据。通过反射,我们可以在不事先知道类型信息的情况下,获取类型信息并操作类型中的成员(如类、方法、属性、字段等)。

一、前置知识

1、编译器

编译器是将源语言程序(如 C#、Java、C 等)翻译为目标语言程序(如机器代码或伪机器代码)的工具。源代码经过编译器的处理后,可以生成可执行文件 (.exe) 或库文件 (.dll) ,供程序运行时使用。

2、程序集(Assembly

程序集是经过编译器编译得到的中间产物,可以是一个库文件 (.dll) 或可执行文件 (.exe)。它是 .NET 程序中的代码集合,包含了类型、方法、属性等元数据,是程序执行的基础。

程序集就是我们写的一个代码集合,我们现在写的所有代码,最终都会被编译器翻译为一个程序集供别人使用。比如一个代码库文件(dll)或者一个可执行文件(exe)

我们新建一个C#项目,运行一次后,系统就会自动在bin目录里生成对应的程序集文件
在这里插入图片描述

3、元数据(Metadata

在C#中,元数据(Metadata)指的是描述程序及其组成部分(如类、方法、属性、字段等)的信息。它是关于代码的“数据”,但并不是实际执行的代码。可以将元数据视为程序代码的“数据字典”,它提供了有关类型、成员和引用等的信息,使得程序在运行时可以进行动态操作。

元数据是随代码一起编译成程序集(Assembly)的一部分,并且可以在运行时通过反射机制进行访问。

元数据是指有关程序结构和组成部分的描述信息,它不仅有助于程序的运行时类型检查,还为反射、动态加载等功能提供了支持。在C#中,元数据通常存储在程序集文件中,并可以通过反射机制访问和操作。

二、反射

1、反射的概念

反射允许程序在运行时查看其他程序集或自身的元数据,动态获取类型信息并对其进行操作。例如,通过反射可以查看类的构造函数、方法、字段、属性等,甚至可以在运行时动态创建对象并调用方法。

2、反射的作用

  • 程序运行时获取类型信息:反射可以帮助我们动态获取类、方法、字段等的元数据信息。
  • 动态操作对象:反射使得我们可以动态实例化对象,调用方法,修改字段值等。
  • 增强灵活性:反射使得代码更加灵活,尤其在插件机制、依赖注入等场景下尤为重要。

3、反射的核心Type

3.1 Type 类介绍

Type 类是反射的基础,它提供了关于类的所有信息,例如类的名称、构造函数、方法、字段、属性等。它是访问元数据的主要方式。

3.2 不同方法获取 Type

  • 通过对象的 GetType() 方法获取:

    int a = 42;
    Type type = a.GetType();
    Console.WriteLine(type);  // 输出: System.Int32
    
  • 通过 typeof 关键字获取:

    Type type = typeof(int);
    Console.WriteLine(type);  // 输出: System.Int32
    
  • 通过类的全名获取:

    Type type = Type.GetType("System.Int32");
    Console.WriteLine(type);  // 输出: System.Int32
    

    其实就是命名空间.类名
    在这里插入图片描述

3.3 获取type类型所在的程序集的相关信息

Console.WriteLine(type.Assembly);

打印

System.Private.CoreLib, Version=9.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e
  • System.Private.CoreLib 是程序集的名称。(通常是 .exe 或 .dll 文件的名称)
  • Version=9.0.0.0 是程序集的版本。
  • Culture=neutral 表示它是通用区域设置的。(如果是通用语言程序集,则为 neutral)。
  • PublicKeyToken=7cec85d7bea7798e 是公共密钥标识符。(用于区分同名的不同程序集版本)。

4、反射的常见用法

为了方便测试反射的常见用法,这里我先新增一个简单的类,里面包含基本的构造函数、方法、字段、属性。

ps:这里只是测试探究,实际开发肯定不需要通过反射来操作自己的类。

class Test
{
    private int i = 1;
    public int j = 2;
    public int k { get; set; }
    public string str = "向宇的客栈";
    public Test() { }
    public Test(int i)
    {
        this.i = i;
    }
    public Test(int i, string str) : this(i)
    {
        this.str = str;
    }
    public void Log()
    {
        Console.WriteLine("学习C#");
    }
}

4.1 获取 Type类型信息

Type t = typeof(Test);// 获取类型信息

4.2 获取类的公共成员

使用 GetMembers() 方法获取类中的所有公共成员:

MemberInfo[] infos = t.GetMembers();
foreach (var info in infos)
{
    Console.WriteLine(info);
}

打印结果
在这里插入图片描述

可以看到,除了万物之父(object)中的方法,打印出来的都是我们前面Test类中定义的公共成员信息(构造函数、方法、字段、属性)。

4.3 获取类的构造函数

  • 获取所有构造函数:
ConstructorInfo[] ctors = t.GetConstructors();
foreach (var ctor in ctors)
{
    Console.WriteLine(ctor);
}

结果
在这里插入图片描述

  • 获取无参构造函数并调用:
ConstructorInfo ctor = t.GetConstructor(Type.EmptyTypes);
Test obj = (Test)ctor.Invoke(null);
Console.WriteLine(obj);
  • 获取有参构造函数并调用:
ConstructorInfo ctor = t.GetConstructor(new Type[] { typeof(int), typeof(string) });
Test obj = (Test)ctor.Invoke(new object[] { 10, "Hello" });
Console.WriteLine(obj);

4.4 获取类的字段

  • 获取所有公共字段:
FieldInfo[] fieldInfos = t.GetFields();
foreach (var field in fieldInfos)
{
    Console.WriteLine(field);
}

结果
在这里插入图片描述

  • 获取指定字段:
FieldInfo fieldInfo = t.GetField("j");
Console.WriteLine(fieldInfo);

结果
在这里插入图片描述

  • 使用反射获取和设置字段的值:
FieldInfo fieldInfo = t.GetField("j");
Test test = new Test();
test.j = 99;
fieldInfo.SetValue(test, 100);
Console.WriteLine(fieldInfo.GetValue(test));  // 输出: 100

4.5 获取类的成员方法

  • 获取所有公共方法(记得引入using System.Reflection;反射命名空间):
using System.Reflection;

MethodInfo[] methods = t.GetMethods();
foreach (var method in methods)
{
    Console.WriteLine(method);
}
  • 获取指定方法并调用:
MethodInfo method = t.GetMethod("ToString");
object result = method.Invoke(test, null);
Console.WriteLine(result);
  • 对于方法重载,需要提供方法的参数类型:
MethodInfo method = t.GetMethod("Substring", new Type[] { typeof(int), typeof(int) });
object result = method.Invoke("Hello, World!", new object[] { 7, 5 });
Console.WriteLine(result);  // 输出: World

4.6 其他反射操作

  • 枚举
    获取枚举类型的名称:

    Enum.GetEnumName(typeof(DayOfWeek), 1);  // 输出: Monday
    
  • 事件
    获取类的事件:

    EventInfo eventInfo = t.GetEvent("MyEvent");
    Console.WriteLine(eventInfo);
    
  • 接口
    获取类实现的接口:

    Type[] interfaces = t.GetInterfaces();
    foreach (var iface in interfaces)
    {
        Console.WriteLine(iface);
    }
    
  • 属性
    获取类的属性:

    PropertyInfo[] properties = t.GetProperties();
    foreach (var property in properties)
    {
        Console.WriteLine(property);
    }
    

5、反射访问并操作私有(private)成员(包括字段、属性、方法等)

在默认情况下,反射是可以访问私有成员的,但你必须明确告诉 .NET 你要访问它们。具体来说,你需要使用 BindingFlags 来指定访问私有成员。

例如,默认情况下,反射会忽略私有字段和方法,但你可以通过显式地指定 BindingFlags.NonPublicBindingFlags.Instance 来让反射能够访问这些私有成员。

示例

// 创建 MyClass 的实例
MyClass myObject = new MyClass();

// 获取 MyClass 类型的信息
Type type = typeof(MyClass);

// 使用反射访问私有字段 secretValue
FieldInfo fieldInfo = type.GetField("secretValue", BindingFlags.NonPublic | BindingFlags.Instance);
if (fieldInfo != null)
{
    // 获取字段的值
    var value = fieldInfo.GetValue(myObject);
    Console.WriteLine("Private Field 'secretValue' Value: " + value);
}

// 使用反射访问私有方法 PrintSecret
MethodInfo methodInfo = type.GetMethod("PrintSecret", BindingFlags.NonPublic | BindingFlags.Instance);
if (methodInfo != null)
{
    // 调用私有方法
    methodInfo.Invoke(myObject, null);
}

这种机制虽然强大,但应谨慎使用,避免破坏封装性,尤其是在生产环境中。这种做法通常用于调试、测试、动态代理等特殊场景。

6、总结

C# 中的反射为程序提供了强大的动态能力,通过 Type 类及其提供的方法,我们可以在运行时获取类型的元数据,动态创建对象,调用方法,甚至修改字段值。

虽然反射提供了灵活性,但是反射的性能较差,因为它是动态查找和操作的。如果频繁使用反射,可能会影响程序性能,尤其是在处理大量数据时。因此应该在合适的场合使用反射,并考虑到性能和可维护性。

三、关键类Assembly和Activator

反射(Reflection)是 C# 中一个非常强大的机制,它允许在运行时访问和操作程序中的类型信息。通过反射,程序可以在运行时动态地获取类、方法、属性等信息,并实例化对象、调用方法、访问字段等。下面是对 AssemblyActivator 这两个关键类的详细介绍和相关用法。

1、反射中的关键类

1.1 Type 类(前面已经介绍过了)

Type 类提供了对类型信息的访问,它是所有类型的元数据的基础。通过 Type 对象,你可以获取类的构造函数、属性、字段、方法等信息。

1.2 Assembly

Assembly 类用于加载和操作程序集。程序集包含了类、接口、枚举等信息,反射可以用来加载程序集,并且在程序运行时查找类型和操作它们。

1.3 Activator

Activator 类位于 System 命名空间下,提供了一组静态方法来创建类型的实例。它常用于在运行时通过反射动态创建对象,特别是在我们事先不知道具体类型的情况下。例如,依赖注入、插件加载、对象池等场景中,可以使用 Activator 来动态实例化对象。

2、使用 Activator 类实例化对象

Activator 提供了几种创建对象的方法,最常用的是 CreateInstance,它可以用来根据 Type 对象动态创建实例。

示例 1:无参构造函数

假设有一个类 Test,它有一个无参构造函数。你可以使用 Activator.CreateInstance 来创建该类的实例。

using System;

public class Test
{
    public string str = "Hello, World!";
}

class Program
{
    static void Main()
    {
        // 获取 Test 类的 Type 对象
        Type testType = typeof(Test);
        
        // 使用 Activator 创建对象实例
        Test testobj = Activator.CreateInstance(testType) as Test;
        
        // 输出结果
        Console.WriteLine(testobj.str);  // Output: Hello, World!
    }
}

示例 2:带参数的构造函数

如果类有带参数的构造函数,可以使用 Activator.CreateInstance 方法传递参数来创建实例。

using System;

public class Test
{
    public int j;
    public string str;

    // 构造函数
    public Test(int j, string str)
    {
        this.j = j;
        this.str = str;
    }
}

class Program
{
    static void Main()
    {
        Type testType = typeof(Test);
        
        // 使用带参数的构造函数
        Test testobj1 = Activator.CreateInstance(testType, 99, "Hello") as Test;
        Console.WriteLine(testobj1.j);  // Output: 99
        Console.WriteLine(testobj1.str);  // Output: Hello
        
        Test testobj2 = Activator.CreateInstance(testType, 55, "World") as Test;
        Console.WriteLine(testobj2.j);  // Output: 55
        Console.WriteLine(testobj2.str);  // Output: World
    }
}

3、使用 Assembly 类加载程序集

前面我们一直都是对当前程序的操作,实际开发肯定是操作外部程序集。Assembly 类使得我们可以在运行时加载、查询、获取外部程序集的类型信息等。

常用方法:

  • GetExecutingAssembly():获取当前执行的程序集。
  • LoadFrom(string path):从指定路径加载程序集。
  • GetTypes():获取程序集中的所有类型。
  • GetType(string typeName):获取指定名称的类型。
  • GetManifestResourceNames():获取程序集中的所有嵌入式资源名称。

3.1 加载程序集:

(1)获取当前执行的程序集:
Assembly assembly = Assembly.GetExecutingAssembly();
Console.WriteLine("当前程序集: " + assembly.FullName);
(2)从指定路径加载程序集:
Assembly assembly = Assembly.LoadFrom("path/to/your/assembly.dll");
Console.WriteLine("加载程序集: " + assembly.FullName);

3.2 获取指定名称的类型

Assembly assembly = Assembly.LoadFrom("path/to/your/assembly.dll");
Type type = assembly.GetType("Namespace.ClassName"); // 获取程序集中的某个类型
Console.WriteLine("类型名称: " + type.FullName);

3.3 获取所有类型:

Assembly assembly = Assembly.LoadFrom("path/to/your/assembly.dll");
Type[] types = assembly.GetTypes();
foreach (Type t in types)
{
    Console.WriteLine(t.FullName); // 输出程序集中的所有类型
}

3.4 获取并调用类型中的方法:

其实就是结合前面Type知识配合使用

Assembly assembly = Assembly.LoadFrom("path/to/your/assembly.dll");
Type type = assembly.GetType("Namespace.ClassName");
MethodInfo methodInfo = type.GetMethod("MethodName");
object result = methodInfo.Invoke(null, null); // 调用静态方法
Console.WriteLine(result);

4、综合示例

我这里项目的程序集文件路径为:C:\Users\zw\Desktop\C#\bin\Debug\net9.0\C#.dll
在这里插入图片描述
程序集文件里主要的代码是,我自定义了一个Test类
在这里插入图片描述

代码

using System;
using System.Reflection;

class Program
{
    static void Main()
    {
        // 加载程序集(因为是反斜杠,所以加个@不希望它转义)
        Assembly assembly = Assembly.LoadFrom(@"C:\Users\zw\Desktop\C#\bin\Debug\net9.0\C#.dll");
        
        // 获取程序集中的所有类型
        Type[] types = assembly.GetTypes();
        
        foreach (var type in types)
        {
            Console.WriteLine(type.Name);
        }
        
        // 获取程序集中的一个具体类型
        Type testType = assembly.GetType("Test");
        
        // 使用反射实例化对象
        object myClassObj = Activator.CreateInstance(testType);

        // 获取并调用方法
        MethodInfo method = testType.GetMethod("Log");
        method.Invoke(myClassObj, null);

        // 获取指定字段并打印值
        FieldInfo field1 = testType.GetField("str");
        Console.WriteLine(field1.GetValue(myClassObj));

        // 获取指定字段,先修改值,在打印值
        FieldInfo field2 = testType.GetField("j");
        field2.SetValue(myClassObj, 100);
        Console.WriteLine(field2.GetValue(myClassObj));
    }
}

结果,程序集里的方法被执行,字段也被打印了(Program类和E_Days枚举是定义的其他两个测试数据,不用管即可)
在这里插入图片描述

四、总结

  • Type:提供关于类、接口、枚举等类型的信息。
  • Assembly:用于加载程序集,可以获取程序集中的所有类型和类型成员信息。
  • Activator:用于在运行时动态创建对象实例,支持无参数和带参数构造函数。
  • 反射虽然非常强大,但会影响性能,因此在需要时使用,避免过度依赖。

专栏推荐

地址
【从零开始入门unity游戏开发之——C#篇】
【从零开始入门unity游戏开发之——unity篇】
【制作100个Unity游戏】
【推荐100个unity插件】
【实现100个unity特效】
【unity框架开发】

完结

赠人玫瑰,手有余香!如果文章内容对你有所帮助,请不要吝啬你的点赞评论和关注,你的每一次支持都是我不断创作的最大动力。当然如果你发现了文章中存在错误或者有更好的解决方法,也欢迎评论私信告诉我哦!

好了,我是向宇,https://xiangyu.blog.csdn.net

一位在小公司默默奋斗的开发者,闲暇之余,边学习边记录分享,站在巨人的肩膀上,通过学习前辈们的经验总是会给我很多帮助和启发!如果你遇到任何问题,也欢迎你评论私信或者加群找我, 虽然有些问题我也不一定会,但是我会查阅各方资料,争取给出最好的建议,希望可以帮助更多想学编程的人,共勉~
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2268408.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

(桌面运维学习)通过备份C盘,进行Windows系统的软件初始化

通过PE工具备份C盘,进行Windows系统的软件初始化 需求场景:快速初始化一批型号和主板一样的电脑系统型号也要一致(Win10专业版就最好全是WIn10专业版),初始化的内容包括已配置好的环境和已安装的软件。主要用于公司桌面…

【ELK】ES单节点升级为集群模式--太细了!

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言准备工作1. 查看现状【单节点】2. 原节点改集群模式3. 改es配置文件,增加集群相关配置项4. *改docker映射的端口* 启动新节点5. docker-compose起一…

Path-of-Thoughts:将“思维链“升级为“思维图“,三阶段框架取代单一推理,提升大模型复杂关系推理准确性至88.2%与效率提升5%

Path-of-Thoughts:将"思维链"升级为"思维图",三阶段框架取代单一推理,提升大模型复杂关系推理准确性至88.2%与效率提升5% 论文大纲理解通用流程框架 观察和假设观察现象提出假设实验验证解法拆解解法:Path-of…

ThinkPHP 8高效构建Web应用-第一个简单的MVC应用示例

【图书介绍】《ThinkPHP 8高效构建Web应用》-CSDN博客 《2025新书 ThinkPHP 8高效构建Web应用 编程与应用开发丛书 夏磊 清华大学出版社教材书籍 9787302678236 ThinkPHP 8高效构建Web应用》【摘要 书评 试读】- 京东图书 使用VS Code开发ThinkPHP项目-CSDN博客 我们先实现一…

No.3十六届蓝桥杯备战|数据类型长度|sizeof|typedef|练习(C++)

数据类型⻓度 每⼀种数据类型都有⾃⼰的⻓度,使⽤不同的数据类型,能够创建出⻓度不同的变量,变量⻓度的不同,存储的数据范围就有所差异。 sizeof操作符 sizeof 是⼀个关键字,也是操作符,专⻔是⽤来计算特…

大数据组件(一)快速入门调度组件Airflow

大数据组件(一)快速入门调度组件Airflow DolphinScheduler和 Airflow是数据领域很流行的两款开源任务调度系统。DolphinScheduler 致力于用可视化的方式去完成一个 DAG 工作流,而 Airflow 则想的是用类似于编程的方式完成一个 DAG 工作流。 Apache DolphinSchedule…

jpeg学习

相关最全的一篇文章链接:https://www.cnblogs.com/wtysos11/p/14089482.html YUV基础知识 Y表示亮度分量:如果只显示Y的话,图像看起来会是一张黑白照。 U(Cb)表示色度分量:是照片蓝色部分去掉亮度&#x…

内部类(3)

大家好,今天我们继续来看看内部类,今天我们来学习一下内部类的分类,我们来看看一共有几种,它们有什么作用,那么话不多说,我们直接开始。 9.1 内部类的分类 先来看下,内部类都可以在一个类的哪些位置进行定…

你还在用rand()生成随机数?

1. rand() 的缺陷 伪随机数生成器使用数学算法来产生具有良好统计特性的数字序列,但这些数字并非真正随机。 C 标准库中的 rand() 函数并不保证所生成的随机序列的质量。某些 rand() 实现生成的数字周期较短,且这些数字是可以预测的。对于有强伪随机数…

基于FPGA的2ASK+帧同步系统verilog开发,包含testbench,高斯信道,误码统计,可设置SNR

目录 1.算法仿真效果 2.算法涉及理论知识概要 2.1 2ASK调制解调 2.2 帧同步 3.Verilog核心程序 4.完整算法代码文件获得 1.算法仿真效果 vivado2019.2仿真结果如下(完整代码运行后无水印): 设置SNR8db 设置SNR20db 整体波形效果&…

RT-Thread中堆和栈怎么跟单片机内存相联系

现在RT-ThreadMCU的应用方式越来越普遍,RT-Thread需要配置MCU中的RAM到的系统中,进入系统内存管理,才能提供给基于实时系统的应用程序使用,比如给应用程序提供malloc、free等函数调用功能。在嵌入式软件开发中,我们经常…

2、Bert论文笔记

Bert论文 1、解决的问题2、预训练微调2.1预训练微调概念2.2深度双向2.3基于特征和微调(预训练下游策略) 3、模型架构4、输入/输出1.输入:2.输出:3.Learned Embeddings(学习嵌入)1. **Token Embedding**2. **Position Embedding**3…

TiDB 的MPP架构概述

MPP架构介绍: 如图,TiDB Server 作为协调者,首先 TiDB Server 会把每个TiFlash 拥有的region 会在TiFlash上做交换,让表连接在一个TiFlash上。另外 TiFlash会作为计算节点,每个TiFlash都负责数据交换,表连接…

3、redis的高可用

主从复制 主从复制:这是redis高可用的基础。哨兵模式和集群都是建立在此基础之上。 主从模式和数据库的主从模式是一样的,主负责写入,然后把写入的数据同步到从,从节点只能读不能写。read only。 不能做高可用的切换&#xff…

【架构-38】如何选择通信协议和数据格式

一、通信协议选择 不同的协议适用于不同的应用场景,关键在于数据传输的需求,如:实时性、带宽、可靠性等。下面是几种常见通信协议的适用场景: WebSocket 适用场景:实时、双向数据传输、低延迟、持久连接 特点&#x…

SpringCloudAlibaba 技术栈—Sentinel

1、什么是sentinel? Sentinel是一个用于微服务架构的流量管理和控制系统,它通过限制和控制进入系统的流量,来保护系统免受过载和故障的影响,确保服务的稳定性。简而言之,它就是一个帮助微服务在高负载情况下也能稳定运行的工具。…

初学STM32 ---高级定时器互补输出带死区控制

互补输出,还带死区控制,什么意思? 带死区控制的互补输出应用之H桥 捕获/比较通道的输出部分(通道1至3) 死区时间计算 举个栗子(F1为例):DTG[7:0]250,250即二进制&#x…

RoboMIND:多体现基准 机器人操纵的智能规范数据

我们介绍了 RoboMIND,这是机器人操纵的多体现智能规范数据的基准,包括 4 个实施例、279 个不同任务和 61 个不同对象类别的 55k 真实世界演示轨迹。 工业机器人企业 埃斯顿自动化 | 埃夫特机器人 | 节卡机器人 | 珞石机器人 | 法奥机器人 | 非夕科技 | C…

Hadoop HA安装配置(容器环境),大数据职业技能竞赛模块A平台搭建,jdk+zookeeper+hadoop HA

HA概述 (1) 所谓HA(High Availablity),即高可用(7*24小时不中断服务)。 (2) 实现高可用最关键的策略是消除单点故障,HA严格来说应该分为各个组件的HA机制,H…

国产文本编辑器EverEdit - 如何让输出窗口的日志具有双击跳转到文件指定行的功能

1 开发参考:编写脚本时如何向输出窗口打印可跳转到文件位置的日志 1.1 应用场景 编写脚本时,有时对文本进行分析,需要将提示信息打印到输出窗口,同时希望将文本的行、列信息也打印在日志中, 最好是双击日志信息可以跳…