C# BindingFlags 使用详解

news2025/3/22 23:58:34

总目录


前言

在 C# 编程的世界里,反射(Reflection)是一个强大且灵活的特性,它允许我们在运行时动态地获取和操作类型的信息。而 BindingFlags 枚举类型,作为反射中的核心概念之一,为我们提供了精确控制类型成员查找和操作的能力(通过组合多个标志来指定搜索类型 如字段、方法、属性等成员 的条件)。今天,就让我们深入探讨 BindingFlags 的使用,解锁反射的更多可能性。


一、什么是 BindingFlags?

1. 定义

BindingFlags 是一个枚举类型,它定义了一系列的标志,用于指定反射操作的搜索条件。它通过组合多个标志(Flags)来控制反射方法(如 GetFieldsGetMethodsGetProperty 等)的行为,使得我们可以灵活地控制要获取或操作的类型成员的范围和特性。

👉 在C#反射编程中,BindingFlags枚举类型是控制成员搜索与操作的核心导航器。

2. 关键特性

  • 类型System.Reflection.BindingFlags (位于 System.Reflection 命名空间)是一个枚举类型。
    • 位标志枚举 :BindingFlags 是一个 位标志枚举[Flags]),支持通过按位或(|)组合多个标志。
  • 作用:通过组合标志,控制反射方法(如 GetType().GetFields()GetType().GetMethods() 等)的搜索行为。
  • 强制指定:必须同时指定 InstanceStatic,以及 PublicNonPublic,否则会返回空结果。

二、常用 BindingFlags 标志详解

1. 常用标志总览

以下是 BindingFlags 中最常用的标志及其作用:

标志作用
Public包括公共成员(如 public 字段、方法、属性)。
NonPublic包括非公共成员(如 privateprotectedinternalprotected internal)。
Instance包括实例成员(非静态成员)。
Static包括静态成员(类级别的成员)。
DeclaredOnly仅搜索当前类型声明的成员,不包括继承的成员。
IgnoreCase忽略成员名称的大小写。
FlattenHierarchy在静态成员搜索中,包含基类的公共和受保护的静态成员(但不包括私有静态成员)。
CreateInstance通过反射创建对象实例(需与 InvokeMember 结合使用)。
InvokeMethod用于调用方法(需与 InvokeMember 结合使用)。
GetField/SetField用于获取或设置字段值(需与 InvokeMember 结合使用)。
GetProperty/SetProperty用于获取或设置属性值(需与 InvokeMember 结合使用)。

2. BindingFlags 的常用枚举值

1)IgnoreCase

当指定 IgnoreCase 时,反射在查找成员时会忽略大小写。这在处理不区分大小写的场景中非常有用。

using System;
using System.Reflection;

public class TestClass
{
    public void MyMethod()
    {
        Console.WriteLine("MyMethod called.");
    }
}

public class Program
{
    public static void Main()
    {
        Type type = typeof(TestClass);
        MethodInfo methodInfo = type.GetMethod("mymethod", BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Public);
        if (methodInfo != null)
        {
            TestClass obj = new TestClass();
            methodInfo.Invoke(obj, null);
        }
    }
}

在这个示例中,即使方法名称是小写的 “mymethod”,通过 BindingFlags.IgnoreCase 也能成功找到并调用 MyMethod 方法。

2)DeclaredOnly

DeclaredOnly 标志用于仅查找在特定类型中声明的成员,而不包括从基类继承的成员。这有助于我们专注于当前类型自身定义的成员。

using System;
using System.Reflection;

public class BaseClass
{
    public void BaseMethod()
    {
        Console.WriteLine("BaseMethod called.");
    }
}

public class DerivedClass : BaseClass
{
    public void DerivedMethod()
    {
        Console.WriteLine("DerivedMethod called.");
    }
}

public class Program
{
    public static void Main()
    {
        Type type = typeof(DerivedClass);
        MethodInfo[] methods = type.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public);
        foreach (MethodInfo method in methods)
        {
            Console.WriteLine(method.Name);
        }
    }
}

运行结果将只输出 DerivedMethod,因为 DeclaredOnly 使得我们只查找在 DerivedClass 中声明的方法,而不包括从 BaseClass 继承的方法。

3)InstanceStatic

InstanceStatic 分别用于指定查找实例成员或静态成员。在反射操作中,必须明确指定要查找的成员类型。

using System;
using System.Reflection;

public class TestClass
{
    public static void StaticMethod()
    {
        Console.WriteLine("StaticMethod called.");
    }

    public void InstanceMethod()
    {
        Console.WriteLine("InstanceMethod called.");
    }
}

public class Program
{
    public static void Main()
    {
        Type type = typeof(TestClass);
        
        // 获取静态方法
        MethodInfo staticMethod = type.GetMethod("StaticMethod", BindingFlags.Static | BindingFlags.Public);
        staticMethod.Invoke(null, null);
        
        // 获取实例方法
        MethodInfo instanceMethod = type.GetMethod("InstanceMethod", BindingFlags.Instance | BindingFlags.Public);
        TestClass obj = new TestClass();
        instanceMethod.Invoke(obj, null);
    }
}

这里分别演示了如何获取和调用静态方法与实例方法,通过指定 BindingFlags.StaticBindingFlags.Instance 来明确查找范围。

4)PublicNonPublic

Public 用于查找公共成员,而 NonPublic 则用于查找非公共成员(包括内部、受保护和私有成员)。这使得我们能够访问类型中不同访问级别的成员。

using System;
using System.Reflection;

public class TestClass
{
    private string privateField;
    internal int internalProperty { get; set; }
    protected void ProtectedMethod()
    {
        Console.WriteLine("ProtectedMethod called.");
    }
}

public class Program
{
    public static void Main()
    {
        Type type = typeof(TestClass);
        TestClass obj = new TestClass();
        
        // 获取私有字段
        FieldInfo privateField = type.GetField("privateField", BindingFlags.NonPublic | BindingFlags.Instance);
        privateField.SetValue(obj, "Private field value");
        Console.WriteLine(privateField.GetValue(obj));
        
        // 获取内部属性
        PropertyInfo internalProperty = type.GetProperty("internalProperty", BindingFlags.NonPublic | BindingFlags.Instance);
        internalProperty.SetValue(obj, 42);
        Console.WriteLine(internalProperty.GetValue(obj));
        
        // 获取受保护方法
        MethodInfo protectedMethod = type.GetMethod("ProtectedMethod", BindingFlags.NonPublic | BindingFlags.Instance);
        protectedMethod.Invoke(obj, null);
    }
}

通过 BindingFlags.NonPublic,我们可以访问类中的私有字段、内部属性以及受保护的方法,这在某些需要深入操作类型内部状态的场景中非常有用。

5)FlattenHierarchy

FlattenHierarchy 标志用于在查找静态成员时,沿着类型层次结构向上搜索,包括基类中的公共和受保护静态成员。这对于需要获取整个继承链中的静态成员时非常方便。

using System;
using System.Reflection;

public class BaseClass
{
    public static void BaseStaticMethod()
    {
        Console.WriteLine("BaseStaticMethod called.");
    }
}

public class DerivedClass : BaseClass
{
    public static void DerivedStaticMethod()
    {
        Console.WriteLine("DerivedStaticMethod called.");
    }
}

public class Program
{
    public static void Main()
    {
        Type type = typeof(DerivedClass);
        MethodInfo[] methods = type.GetMethods(BindingFlags.FlattenHierarchy | BindingFlags.Static | BindingFlags.Public);
        foreach (MethodInfo method in methods)
        {
            Console.WriteLine(method.Name);
        }
    }
}

运行结果将输出 BaseStaticMethodDerivedStaticMethod,因为 FlattenHierarchy 使得我们能够获取基类和派生类中的所有公共静态方法。

3. BindingFlags 的组合使用

BindingFlags 是一个位域枚举,这意味着我们可以使用按位或运算符(|)组合多个枚举值,以指定多个绑定条件。这为我们提供了极大的灵活性,能够满足各种复杂的反射需求。

using System;
using System.Reflection;

public class TestClass
{
    private int privateField;
    public void PublicMethod()
    {
        Console.WriteLine("PublicMethod called.");
    }
    private void PrivateMethod()
    {
        Console.WriteLine("PrivateMethod called.");
    }
}

public class Program
{
    public static void Main()
    {
        Type type = typeof(TestClass);
        TestClass obj = new TestClass();
        
        // 获取所有实例方法(公共和非公共)
        MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
        foreach (MethodInfo method in methods)
        {
            Console.WriteLine(method.Name);
        }
        
        // 获取私有字段
        FieldInfo privateField = type.GetField("privateField", BindingFlags.NonPublic | BindingFlags.Instance);
        privateField.SetValue(obj, 123);
        Console.WriteLine(privateField.GetValue(obj));
    }
}

在这个示例中,我们组合了 BindingFlags.InstanceBindingFlags.PublicBindingFlags.NonPublic 来获取类型中的所有实例方法,无论是公共的还是非公共的。同时,也演示了如何获取和操作私有字段。

4. BindingFlags基础配置规则

1)成员类型必选项

必须包含InstanceStatic标志中的一个(或同时包含):

// 获取所有公共实例成员(默认配置)
var publicMembers = type.GetMembers(BindingFlags.Public | BindingFlags.Instance);

// 获取私有静态字段
var privateStaticField = type.GetField("_cache", 
    BindingFlags.NonPublic | BindingFlags.Static);

原理:反射引擎需要明确区分实例成员与静态成员的搜索范围。

2)访问权限必选项

必须包含PublicNonPublic标志中的一个(或同时包含):

// 获取所有非公共方法(含私有和受保护)
var nonPublicMethods = type.GetMethods(
    BindingFlags.NonPublic | BindingFlags.Instance);

// 获取公共静态属性
var staticProperty = type.GetProperty("Logger",
    BindingFlags.Public | BindingFlags.Static);

注意:若未指定访问权限标志,默认仅搜索公共成员。

5. 典型组合示例

以下是一些典型场景的 BindingFlags 组合:

1)获取公共实例字段

Type type = typeof(MyClass);
// 公共 + 实例
BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.Instance;

FieldInfo[] fields = type.GetFields(bindingFlags); 

2)获取私有静态方法

// 非公共 + 静态
BindingFlags bindingFlags = BindingFlags.NonPublic | BindingFlags.Static;

MethodInfo method = typeof(MyClass).GetMethod("PrivateMethod", bindingFlags); 

3)获取所有实例属性(包括私有)

// 实例 + 公共 + 非公共
BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;

PropertyInfo[] properties = typeof(MyClass).GetProperties(bindingFlags); 

4)获取当前类型声明的所有字段(不包括继承的)

// 仅当前类型声明的字段
BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.NonPublic | BindingFlags.Public;

FieldInfo[] declaredFields = typeof(MyClass).GetFields(
    BindingFlags.DeclaredOnly | 
    BindingFlags.Instance | 
    BindingFlags.Public | 
    BindingFlags.NonPublic); 

5)忽略继承的成员

// 仅当前类型声明的私有实例字段
BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.NonPublic;

FieldInfo[] declaredFields = typeof(MyClass).GetFields(bindingFlags); 

6)忽略大小写搜索

// 忽略大小写获取字段 "MyField"
BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.IgnoreCase | BindingFlags.Public;

FieldInfo field = typeof(MyClass).GetField("myfield", bindingFlags);

三、实际应用场景

1. 访问不同条件下的成员

1)访问私有字段

public class MyClass
{
    private int _privateField;
}

// 通过反射获取私有字段
FieldInfo field = typeof(MyClass).GetField(
    "_privateField", 
    BindingFlags.NonPublic | BindingFlags.Instance);

// 设置字段值
var instance = new MyClass();
field.SetValue(instance, 42);

2)获取所有属性(包括私有)

public class MyClass
{
    public string PublicProp { get; set; }
    private int PrivateProp { get; set; }
}

// 获取所有属性(公共 + 私有)
PropertyInfo[] properties = typeof(MyClass).GetProperties(
    BindingFlags.Instance | 
    BindingFlags.Public | 
    BindingFlags.NonPublic);

3)忽略继承的成员

public class BaseClass
{
    public string BaseField;
}

public class DerivedClass : BaseClass
{
    public string DerivedField;
}

// 仅获取 DerivedClass 自身的字段
FieldInfo[] fields = typeof(DerivedClass).GetFields(
    BindingFlags.DeclaredOnly | 
    BindingFlags.Public | 
    BindingFlags.Instance);
// fields 包含 DerivedField,但不包含 BaseField

2. 动态调用复杂方法

1)调用私有方法

object instance = Activator.CreateInstance(type);
MethodInfo privateMethod = type.GetMethod("InternalProcess",BindingFlags.NonPublic | BindingFlags.Instance);
privateMethod.Invoke(instance, new object[] { data });

2)通过InvokeMember动态操作

// 设置私有静态字段值
type.InvokeMember("_instanceCount", 
    BindingFlags.SetField | BindingFlags.NonPublic | BindingFlags.Static,
    null, null, new object[] { 10 });

// 调用重载方法(指定参数类型)
object result = type.InvokeMember("Parse",
    BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Static,
    null, null, new object[] { "2023", CultureInfo.CurrentCulture });

四、使用须知

1. 关键注意事项

1)必须指定实例Instance或静态Static标志

在使用反射查找类型成员时,必须指定 InstanceStatic 标志之一,否则将返回空数组或 null

// 错误:未指定 Instance 或 Static
var fields = type.GetFields(BindingFlags.Public); // 返回空数组

// 正确:同时指定 Public 和 Instance
var fields = type.GetFields(BindingFlags.Public | BindingFlags.Instance);

2)必须指定公共Public或非公共NonPublic标志

同样,需要指定 PublicNonPublic 标志之一来确定要查找的成员的访问级别

// 错误:未指定 Public 或 NonPublic
var fields = type.GetFields(BindingFlags.Instance); // 返回空数组

// 正确:同时指定 NonPublic 和 Instance
var fields = type.GetFields(BindingFlags.NonPublic | BindingFlags.Instance);

3)默认绑定规则

如果不指定任何 BindingFlags,默认情况下将查找公共的实例和静态成员。

4)DeclaredOnly 的限制

  • 仅搜索当前类型声明的成员,不包括继承的成员。
  • 示例
    public class Base { public string BaseField; }
    public class Derived : Base { public string DerivedField; }
    
    // 仅获取 Derived 自身的字段
    var fields = typeof(Derived).GetFields(
        BindingFlags.DeclaredOnly | 
        BindingFlags.Public | 
        BindingFlags.Instance); // 只包含 DerivedField
    

5)FlattenHierarchy 的适用场景

  • 仅对静态成员有效,且不包含基类的私有静态成员。
  • 示例
    // 获取基类和当前类的公共静态方法
    var methods = typeof(Derived).GetMethods(
        BindingFlags.FlattenHierarchy | 
        BindingFlags.Public | 
        BindingFlags.Static);
    

6)IgnoreCase 的使用场景

  • 仅在需要忽略名称大小写时使用,例如处理用户输入的模糊匹配。

2. 性能优化技巧

// 缓存高频访问的MemberInfo对象
private static readonly MethodInfo _cachedMethod = 
    typeof(DataProcessor).GetMethod("Encrypt",
        BindingFlags.NonPublic | BindingFlags.Instance);

// 使用Expression Tree编译动态调用(比纯反射快10倍以上)
var instanceParam = Expression.Parameter(typeof(DataProcessor));
var callExpr = Expression.Call(instanceParam, _cachedMethod);
var lambda = Expression.Lambda<Action<DataProcessor>>(callExpr, instanceParam)
                      .Compile();
lambda.Invoke(processor);

3. 常见错误与解决方案

Q1:为什么返回空数组?

  • 原因:未正确组合 BindingFlags(如缺少 InstanceNonPublic)。
  • 解决:确保同时指定 Instance/StaticPublic/NonPublic

Q2:访问基类成员失败

  • 原因:使用了 DeclaredOnly 标志。
  • 解决:移除 DeclaredOnly 或接受仅当前类型的成员。

Q3:调用方法时参数类型不匹配?

  • 原因:未指定 ExactBinding 或参数类型不匹配。
  • 解决:确保参数类型与方法签名一致,或使用 ExactBinding 强制类型匹配。

4. 总结

  • BindingFlags 是反射的“导航仪”,通过组合标志精确控制搜索范围。
  • 关键规则
    1. 必须指定成员类型: InstanceStatic(或两者)。
    2. 必须指定访问权限: PublicNonPublic(或两者)。
    3. 使用 DeclaredOnly 时仅搜索当前类型声明的成员。
  • 典型组合
    • 公共实例成员:BindingFlags.Public | BindingFlags.Instance
    • 私有静态方法:BindingFlags.NonPublic | BindingFlags.Static
    • 所有实例字段:BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic

掌握BindingFlags的配置逻辑可显著提升反射代码的精准度与可靠性。


结语

回到目录页:C#/.NET 知识汇总
希望以上内容可以帮助到大家,如文中有不对之处,还请批评指正。

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

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

相关文章

【亚马逊云科技】大模型选型实战(挑选和测评对比最适合业务的大模型)

文章目录 前言1、实验内容2、手册内容 一、环境准备二、Prompt 实战与模型配置2.1 基于 Amazon Bedrock 对比测试不同模型的逻辑推理效果2.2 基于 Amazon Bedrock 对比测试不同模型知识问答能力2.3 Prompt 实战结果分析 三、基于 Amazon Bedrock Evaluations 进行模型评测与自动…

调用feapder作为子程序时setting.py文件不起作用

feaper 官方文档地址&#xff1a; 简介及安装 - feapder官方文档|feapder-document 问题&#xff1a; 在最近的开发中需要调用feapder作为主程序调用的子程序时发现自动入库时无法入库&#xff0c;通过查看日志信息发现连接数据库时被拒绝连接了&#xff0c;但是我的setting.p…

【从零开始学习计算机科学】软件测试(九)Web系统测试 与 数据库测试

【从零开始学习计算机科学】软件测试(九)Web系统测试 与 数据库测试 Web系统测试Web系统基本组成Web系统的服务器端应用特点Web系统测试的分类Web应用系统测试的实施功能测试链接测试表单测试性能测试连接速度测试负载测试压力测试可用性测试导航测试图形测试内容测试表格测试…

G-Star 校园开发者计划·黑科大|开源第一课之 Git 入门

万事开源先修 Git。Git 是当下主流的分布式版本控制工具&#xff0c;在软件开发、文档管理等方面用处极大。它能自动记录文件改动&#xff0c;简化合并流程&#xff0c;还特别适合多人协作开发。学会 Git&#xff0c;就相当于掌握了一把通往开源世界的钥匙&#xff0c;以后参与…

5.0 VisionPro调用USB相机的方法与步骤说明(一)

本文介绍如何在C#中调用visionPro以处理USB相机采集到的图片。示例如下: 主要思路如下: 1. 使用AForge来打开以及采集usb相机照片。 usb相机处于一直运行状态。每隔100ms采集一次照片。且触发一次事件。 public void Start() { this.videoSourcePlayer.Stop(); …

微信小程序计算属性与监听器:miniprogram-computed

小程序框架没有提供计算属性相关的 api &#xff0c;但是官方为开发者提供了拓展工具库 miniprogram-computed。 该工具库提供了两个功能&#xff1a; 计算属性 computed监听器 watch 一、安装 miniprogram-computed 在项目的根目录下&#xff0c;使用如下命令&#xff0c;…

强大的AI网站推荐(第二集)—— V0.dev

网站&#xff1a;V0.dev 号称&#xff1a;前端开发神器&#xff0c;专为开发人员和设计师设计&#xff0c;能够使用 AI 生成 React 代码 博主评价&#xff1a;生成的UI效果太强大了&#xff0c;适合需要快速创建UI原型的设计师和开发者 推荐指数&#xff1a;&#x1f31f;&…

整理和总结微信小程序的高频知识点

前言 近期萌生了一些想法&#xff0c;感觉可以做一个小程序作为产出。 但小程序做得比较少&#xff0c;因此边做边复习。整理和总结了一些高频知识点和大家一起分享。 一、模板和组件 1.1模板&#xff08;Template&#xff09; 优势 简单灵活&#xff1a;模板定义和使用都较…

vue中js简单创建一个事件中心/中间件/eventBus

vue中js简单创建一个事件中心/中间件/eventBus 目录结构如下&#xff1a; eventBus.js class eventBus {constructor() {this.events {};}// 监听事件on(event, callback) {if (!this.events[event]) {this.events[event] [];}this.events[event].push(callback);}// 发射…

# [RPA] 使用八爪鱼进行高效网页数据采集

在许多行业中&#xff0c;数据是核心资产。然而&#xff0c;虽然许多网站的文本内容可以免费访问&#xff0c;但手动一条一条采集&#xff0c;不仅耗时耗力&#xff0c;还容易出错。这种情况下&#xff0c;使用自动化工具来提高采集效率就显得尤为重要。本文将介绍 八爪鱼 这一…

K8S学习之基础三十七:prometheus监控node资源

Prometheus v2.2.1 ​ 编写yaml文件&#xff0c;包含创建ns、configmap、deployment、service # 创建monitoring空间 vi prometheus-ns.yaml apiVersion: v1 kind: Namespace metadata:name: monitor-sa# 创建SA并绑定权限 kubectl create serviceaccount monitor -n monito…

#mapreduce打包#maven:could not resolve dependencies for project

打包报错&#xff1a; #报错信息&#xff1a; [ERROR] Failed to execute goal on project mapreduce_teacher1: Could not resolve dependencies for project org.example:mapreduce_teacher1:jar:1.0-SNAPSHOT: Failed to collect dependencies at org.apache.hive:hive-exe…

QT软件匠心开发,塑造卓越设计服务

在当今这个数字化飞速发展的时代&#xff0c;软件已经成为我们生活中不可或缺的一部分。而QT&#xff0c;作为一款跨平台的C图形用户界面应用程序开发框架&#xff0c;凭借其强大的功能和灵活性&#xff0c;在众多软件开发工具中脱颖而出。我们深知&#xff0c;在软件开发领域&…

田间机器人幼苗视觉检测与护苗施肥装置研究(大纲)

田间机器人幼苗视觉检测与护苗施肥装置研究 基于多光谱视觉与精准施肥的农业机器人系统设计 第一章 绪论 1.1 研究背景与意义 农业智能化需求&#xff1a; 传统幼苗检测依赖人工&#xff0c;效率低且易遗漏弱苗/病苗施肥不精准导致资源浪费和环境污染 技术挑战&#xff1a;…

生物化学笔记:医学免疫学原理 免疫系统的组成与功能+克隆选择学说

免疫系统的组成与功能 克隆选择学说 克隆选择学说&#xff08;Clonal Selection Theory&#xff09;是免疫学的核心理论之一&#xff0c;由 麦克法兰伯内特&#xff08;Frank Macfarlane Burnet&#xff09; 在 1957 年提出&#xff0c;用于解释特异性免疫反应的机制。 基本概…

Android 15 获取网络切片信息的标准接口

相关术语 简称全称中文说明URSPUE Route Selection Policy用户路由选择策略URSP 是 5G 核心网(PCF)下发给 UE 的策略,用于指导应用流量如何路由到不同的网络切片或 PDU 会话。其包含多个规则,每条规则由 优先级、业务描述符(Traffic Descriptor) 和 路由选择描述符(Rout…

使用【docker】+【shell】脚本半自动化部署微服务项目

一.前言 以下是一个基于 ‌Docker Shell脚本‌ 的半自动化部署方案&#xff0c;包含镜像构建、容器管理、网络配置和日志监控等核心功能&#xff0c;适用于大多数Web应用或微服务项目。 二‌.目录结构 三.脚本代码实现 1.‌Shell脚本实现 (deploy.sh) #!/bin/bash# 设置颜…

使用 GitHub 可重用工作流和 GitHub Actions 简化 DevOps

在当今的 DevOps 环境中&#xff0c;自动化是开发团队能够更快地交付功能并维护高质量代码库的关键。这就是像 GitHub Actions 这样的工具变得不可或缺的地方&#xff0c;因为它能够直接在存储库中自动化、自定义和执行 GitHub 工作流程。 当然&#xff0c;随着项目的规模和存…

Sql Server 索引性能优化 分析以及分表

定位需优化语句 根据工具 skywking 或者开启慢查询日志 找到 慢sql 的语句根据 执行过程 来 判断 慢的原因 row filter 指标 看查了多少数据 比例多少 type 看下是单表 还是 join联表 比如 执行步骤多 没索引 优化方向 减少执行次数索引 没索引考虑加索引 加索引 尽量选择 i…

vue使用element-ui自定义样式思路分享【实操】

前言 在使用第三方组件时&#xff0c;有时候组件提供的默认样式不满足我们的实际需求&#xff0c;需要对默认样式进行调整&#xff0c;这就需要用到样式穿透。本篇文章以vue3使用element-ui的Tabs组件&#xff0c;对Tabs组件的添加按钮样式进行客制化为例。 确定需要修改的组…