c#的特性和反射(二)

反射和特性(详细)

反射

C# 复制代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace _03_反射
{
    internal class Program
    {
        static void Main(string[] args)
        {
            // System.Reflection 命名空间中的类与 System.Type 使你能够获取有关加载的程序集和其中定义的类型的信息,如类、接口和值类型(即结构和枚举)。
            // 可以使用反射在运行时创建、调用和访问类型实例。

            // 反射就是提供了一种可以动态访问程序集成员的一种方案

            // ----------------反射可以让我们动态的添加程序
            // 使用反射动态的加载程序
            Assembly assembly = Assembly.LoadFile(@"C:\Users\g8496\Desktop\11-6\01 作业\bin\Debug\01 作业.exe");
            Type[] types = assembly.GetTypes();
            foreach (Type type in types)
            {
                Console.WriteLine(type.FullName);
            }

            // ---------------反射可以根据类型读取该类型中的信息
            // System.Type  一般上作为我们使用反射的入口,大部分反射的操作都要使用 System.Type来完成
            // Type 是一个类,存储某个类型的详细信息,也就是元数据(metadata),可以用它获取到该类的属性和方法
            Type t1 = typeof(string);   // 使用 typeof(类型) 获取该类型的详细信息
            Type t2 = typeof(int);
            Type t3 = typeof(Dog);

            Dog dog = new Dog();    // 根据现有对象获取类型的详细信息
            Type t4 = dog.GetType();


            // ------------------使用Type获取某个类的所有属性
            // 1、根据对应的类型生成Type对象
            Type d = typeof(Dog);
            // 2、调用方法获取属性
            PropertyInfo[] infos = d.GetProperties();
            // 3、循环所有的属性
            foreach (PropertyInfo info in infos)
            {
                Console.WriteLine(info.Name);   // 属性的名字
            }


            Console.ReadLine();
        }
    }
}

动态加载DLL

C# 复制代码
using ClassLibrary;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace _04_动态加载DLL
{
    internal class Program
    {
        static void Main(string[] args)
        {
            // 我们可以使用反射来动态的读取dll文件中的元数据,包括这个dll中有哪些类、属性、方法


            // Load     只写dll的文件名,但是要保证当前项目的运行目录中有该dll文件    
            // Assembly as1 =  Assembly.Load("ClassLibrary");

            // LoadFile 加载指定路径下的dll文件,需要写绝对路径(从盘符(C: D:)开始的路径)
            // Assembly as2 = Assembly.LoadFile(@"C:\Users\g8496\Desktop\11-6\04 动态加载DLL\bin\Debug\ClassLibrary.dll");

            // LoadFrom 加载指定路径下的dll文件,支持绝对路径和相对路径(注意:要带文件后缀)
            Assembly as3 =  Assembly.LoadFrom(@"ClassLibrary.dll");


            // Assembly 加载了对应的dll后,其中存储了该程序中所有的类型

            // GetTypes()   获取该dll/exe中所有的类型
            Type[] ts = as3.GetTypes();
            foreach (Type v in ts)
            {
                // Type.FullName    获取该类型的完全限定名(带有命名空间的类名)
                // Type.Name        获取该类型的名字(类名)
                Console.WriteLine($"v.FullName: {v.FullName}    Name:{v.Name}");
            }


            // Type至关重要,它是对程序元数据访问和操作的入口
            Type t = typeof(People);    // 根据类获取类型
            Console.WriteLine(t.FullName); 

            Type t1 = new People().GetType();   // 根据对象获取类型
            Console.WriteLine(t1.FullName);


            // 封装方法输出完全限定名
            WriteFullName<string>();
            WriteFullName<Dog>();
            Console.ReadLine();
        }

        // 输出类的完全限定名
        static void WriteFullName<T>()
        {
            Type t = typeof(T);
            Console.WriteLine(t.FullName);
        }
    }
}

反射操作

C# 复制代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using ClassLibrary;

namespace _05_反射操作
{
    internal class Program
    {
        static void Main(string[] args)
        {
            Assembly assembly = Assembly.LoadFrom("ClassLibrary.dll");

            // GetTypes 获取dll中所有的类型
            Type[] types = assembly.GetTypes();
            // GetType  获取程序中指定的类型,参数为对应类型的完全限定名(带命名空间的)
            Type t = assembly.GetType("ClassLibrary.User");

            // 使用 Type.GetProperties    获取该类型的所有属性
            PropertyInfo[] infos = t.GetProperties();
            foreach (PropertyInfo info in infos)
            {
                Console.WriteLine("属性:" + info.Name + "类型:" + info.PropertyType);
            }
            // 使用   Type.GetMethods   获取该类型的所有方法
            // 包含属性的get、set,以及类自己的方法,还有继承自父类的方法
            MethodInfo[] methods =  t.GetMethods();
            foreach (MethodInfo method in methods)
            {
                Console.WriteLine("方法" + method.Name);
            }

            Console.WriteLine("----------------------------------");

            // 使用反射实例化类
            {
                // 根据某个类型信息生成实例(new操作),执行无参构造
                object o = Activator.CreateInstance(t);
            }
            {
                // 执行有参构造方法创建对象
                object o1 = Activator.CreateInstance(t, new object[] { "1","张三","155555",11});
                object o2 = Activator.CreateInstance(t, new object[] { "张三", 18 });
            }
            {
                // 获取类型的所有构造方法(了解)
                ConstructorInfo[] ctors = t.GetConstructors();  // 获取所有构造方法
                foreach (ConstructorInfo ctor in ctors) 
                {
                    Console.WriteLine(ctor.Name);   // 构造方法的名字都是  .ctor
                    ParameterInfo[] parameters = ctor.GetParameters();  // 获取当前构造方法的参数列表
                    Console.WriteLine(parameters.Length); // 当前构造方法的参数个数
                    Console.Write("所需参数:");
                    foreach (ParameterInfo v in parameters) // 循环参数列表
                    {
                        // v.Name   参数名
                        // v.ParameterType  参数类型
                        Console.WriteLine(v.Name + ":" + v.ParameterType);
                    }
                    Console.WriteLine();
                }
            }
            Console.WriteLine("------------------------");
            {
                // 使用反射,即使该类的访问修饰符为:internal,照样可以通过反射访问它并实例化

                // new Dog();       报错,因此Dog的修饰符为internal
                Type d = assembly.GetType("ClassLibrary.Dog");
                object o = Activator.CreateInstance(d);


                // new ClassLibrary.Cai.Qiu.Kun();      报错,因为构造方法是私有的
                Type d1 = assembly.GetType("ClassLibrary.Cai.Qiu.Kun");
                object o1 = Activator.CreateInstance(d1, true); // 参数2给一个true,表示该构造方法可能为非公开(非 public)的
            }




            Console.ReadLine();
        }
    }
}

使用反射创建泛型类

C# 复制代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using ClassLibrary;

namespace _06_使用反射创建泛型类
{
    internal class Program
    {
        static void Main(string[] args)
        {
            //new TestTClass<int, string, bool>(1, "测试", true);
            //new TestTClass<int, double, char>(1, 2.2, 'c');

            // 如何使用反射创建泛型类
            // 1、加载程序
            Assembly assembly = Assembly.LoadFrom("ClassLibrary.dll");
            // 2、获取对应的类型(注意:如果该类型拥有泛型参数,需要以 `数字   结尾,数字取决于泛型的个数)
            Type t = assembly.GetType("ClassLibrary.TestTClass`3");
            // 3、带有泛型参数的类型其实是一个不完整的类型,因此带有泛型参数的类型不能直接使用,需要指定对应的泛型参数
            // 根据泛型类型生成新的类型
            // 注意:传入的应该是一个 Type 类型,使用 typeof 生成
            Type newT = t.MakeGenericType(typeof(int), typeof(string), typeof(bool));

            // newT  == TestTClass<int, string, bool>

            // 4、进行实例化
            object o = Activator.CreateInstance(newT, new object[] {123,"张三",false});

            Console.ReadLine();
        }
    }
}

使用反射调用方法

C# 复制代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using TestLibrary;

namespace _02_使用反射调用方法
{
    internal class Program
    {
        static void Main(string[] args)
        {
            // 1、加载程序
            Assembly assembly = Assembly.LoadFrom("TestLibrary.dll");
            // 2、获取对应的类型
            Type peopleType = assembly.GetType("TestLibrary.People");
            // 3、创建实例化对象
            object o1 = Activator.CreateInstance(peopleType, new object[] { "张三", 20 });
            object o2 = Activator.CreateInstance(peopleType, new object[] { "李四", 21 });

            Console.WriteLine("----------------调用无参的方法---------------");
            {
                // 不适用委托调用方法:
                // People p1 = new People();
                // p1.Say();

                // 使用反射调用方法
                // 1、获取该类型中对应名字的方法
                MethodInfo method = peopleType.GetMethod("Eat");
                // 2、调用方法,
                // 参数1:指定该方法在哪个实例上运行
                // 参数2:调用方法传递的参数,如果没有参数可以传null
                method.Invoke(o1, null);    // 我张三会吃饭

                method.Invoke(o2, null);    // 我李四会吃饭
            }
            Console.WriteLine("---------------调用有参构造-------------------");
            {
                MethodInfo method = peopleType.GetMethod("Play");
                method.Invoke(o1, new object[] { "穿越火线" });
                method.Invoke(o1, new object[] { "元神启动" });
                method.Invoke(o2, new object[] { "PUBG" });
            }
            Console.WriteLine("---------------调用重载方法-------------------");
            {
                // 如果一个方法拥有多个重载,那么在获取该方法时就必须手动指定方法的类型
                MethodInfo method = peopleType.GetMethod("Say", new Type[] { });
                method.Invoke(o1, null);

                MethodInfo method1 = peopleType.GetMethod("Say", new Type[] { typeof(string) });
                method1.Invoke(o1, new object[] { "小红叫我去网吧,我置之不理" });

                MethodInfo method2 = peopleType.GetMethod("Say", new Type[] { typeof(string), typeof(string) });
                method2.Invoke(o1, new object[] { "今天上网吧打通宵", "小明"   });
            }
            Console.WriteLine("---------------调用私有方法-------------------");
            {
                // 调用私有方法
                MethodInfo method = peopleType.GetMethod("Test", BindingFlags.Instance | BindingFlags.NonPublic);
                method.Invoke(o2, null);

                // 调用私有的重载方法
                // Type.GetMethod(方法名, BindingFlags.Instance | BindingFlags.NonPublic, null, new Type[]{ 参数类型 }, null)
                MethodInfo method1 = peopleType.GetMethod("Test1", BindingFlags.Instance | BindingFlags.NonPublic, null, new Type[] { typeof(string) }, null);
                method1.Invoke(o2, new object[] {"测试"});

                MethodInfo method2 = peopleType.GetMethod("Test1", BindingFlags.Instance | BindingFlags.NonPublic, null, new Type[] { typeof(string), typeof(int) }, null);
                method2.Invoke(o2, new object[] { "测试222", 999 });
            }

            // 重要:GetMethod     Invoke

            Console.ReadLine();
        }
    }
}

属性操作

C# 复制代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using TestLibrary;

namespace _03_属性操作
{
    internal class Program
    {
        static void Main(string[] args)
        {
            // 1、加载程序
            Assembly assembly = Assembly.LoadFrom("TestLibrary.dll");
            // 2、获取类型
            Type peopleType = assembly.GetType("TestLibrary.People");
            
            
            // 创建实例
            object o = Activator.CreateInstance(peopleType);

            // 1、获取类型中所有的属性
            PropertyInfo[] infos = peopleType.GetProperties();
            foreach (PropertyInfo pi in infos)
            {
                Console.WriteLine($"属性名:{pi.Name} 类型:{pi.PropertyType}");
            }


            {
                // 2、使用反射设置对象的属性
                // 2-1、先获取对应的属性
                PropertyInfo nameInfo = peopleType.GetProperty("Name");
                // 2-2、设置对应对象的属性值
                // 参数1:设置到哪个对象上
                // 参数2:设置的属性值
                nameInfo.SetValue(o, "张三");

                // 设置对象o的Age属性为22
                PropertyInfo a = peopleType.GetProperty("Age");
                a.SetValue(o, 22);
            }

            {
                // 3、使用反射读取对象的属性
                // 3-1、获取对应的属性
                PropertyInfo nameInfo = peopleType.GetProperty("Name");
                // 3-2、读取对应对象的属性值
                Console.WriteLine("o对象的Name属性值为:" + nameInfo.GetValue(o));
            }


            Console.WriteLine("============");
            // 在控制台输出该参数的所有属性名、属性值、属性类型
            People p1 = new People();
            Test.Fn(p1);
            Test.Fn(new People() { Name = "万物", Age = 30 });



            Console.ReadLine();
        }
    }

    class Test
    {
        public static void Fn<T>(T v)
        {
            // 1、获取该类型的Type
            Type t = typeof(T);
            // Type t = v.GetType(); // 或者

            // 2、获取该Type的所有属性
            PropertyInfo[] properties = t.GetProperties();

            // 3、循环所有属性
            foreach (PropertyInfo pi in properties) {
                // 输出属性名,属性类型,属性值
                Console.WriteLine($"{pi.Name}: {pi.PropertyType} = {pi.GetValue(v)}");
            }
        }
    }
}

特性

C# 复制代码
// #define abc     // 定义一个预处理标识   abc
// 一般预处理标识仅在当前文件中生效,如果需要该标识在整个项目中生效,需要在项目的Properties

using System;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _05_特性
{
    internal class Program
    {
        static void Main(string[] args)
        {
            // 什么是特性
            // **特性(Attribute)**是用于在运行时传递程序中各种元素(比如类、方法、结构、枚举、组件等)的行为信息的声明性标签。您可以通过使用特性向程序添加声明性信息。一个声明性标签是通过放置在它所应用的元素前面的方括号([ ])来描述的。
            // 特性(Attribute)用于添加元数据,如编译器指令和注释、描述、方法、类等其他信息。

            // .Net 框架提供了两种类型的特性:预定义特性(内置特性)和自定义特性。

            // 特性的语法如下
            // 特性(Attribute)的名称和值是在方括号内规定的,放置在它所应用的元素之前。positional_parameters 规定必需的信息,name_parameter 规定可选的信息。

            // [attribute(必须的信息1, 必须的信息2, 可选的信息 = value, 可选的信息 = value)]
            // 元素

            // 特性就是给C#中的元素(类、属性、字段、方法...)添加一些其他的信息

            // 预定义特性(内置特性)
            Test test = new Test();
            test.Fn();
            test.Fn1();
            test.Fn2();
            test.Fn3();

            for (int i = 0; i < 100; i++)
            {
                test.TestMethodSpeed();
            }
            new Class1().Fn();

            Console.WriteLine("Obsolete特性");
            test.Fn4();
            test.Fn5();
            // test.Fn7();

            Console.ReadLine();
        }
    }

    class Test
    {
        // Conditional(名字)      该特性标记了一个条件,如果执行编译时定义了该预处理标识符,这个属性或者方法才会被定义和调用
        [Conditional("abc")]
        public void Fn()
        {
            Console.WriteLine("我是Fn方法,abc标识被定义时执行");
        }
        [Conditional("abc")]
        public void Fn1()
        {
            Console.WriteLine("我是Fn1方法,abc标识被定义时执行");
        }
        [Conditional("DEBUG")]
        public void Fn2()
        {
            Console.WriteLine("我是Fn2,DEBUG标识被定义时执行");
        }
        [Conditional("aaa")]
        public void Fn3()
        {
            Console.WriteLine("我是Fn3,aaa标识被定义时执行");
        }


        // 测试方法的速度
        [Conditional("DEBUG")]
        public void TestMethodSpeed()
        {
            Console.WriteLine("假装测试方法的执行速度,DEBUG标识被定义时执行");
        }

        [Obsolete("这个方法不让用了")]
        public void Fn4() { }
        [Obsolete("Fn5已经过时,请你使用Fn6方法")]
        public void Fn5() { }
        public void Fn6() { }

        // 参数2传递一个布尔值,表示如果使用该方法是是否展示一个错误而不是警告
        [Obsolete("提示信息", true)]
        public void Fn7() { }


        // 同时使用多个特性
        [Conditional("DEBUG")]
        [Obsolete("过时了")]
        public void Fn8()
        {

        }

        // 同时使用多个特性的另一种写法
        [Conditional("DEBUG"), Obsolete("过时了")]
        public void Fn9()
        {

        }
    }
}

自定义特性

C# 复制代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _06_自定义特性
{
    // 自定义特性就是一个类,需要继承子Attribute
    // 一般我们自定义的特性都以Attribute结尾,在使用该特性时可以省略Attribute

    // 创建了一个特性,该特性用于记录某个元素的bug修复情况
    public class BugFixAttribute : Attribute
    {
        // bug修复者
        public string Name { get; set; }
        // bug修复时间
        public string Time { get; set; }
        // bug的描述信息
        public string Description { get; set; }
        public BugFixAttribute(string name, string time)
        {
            Name = name;
            Time = time;
        }
    }
    public class LaoguoAttribute: Attribute {
        public int  A { get; set; }
        public string B { get; set; }
        public LaoguoAttribute(int a)
        {
            A = a;
        }
    }
    // 有一个内置的特性用于规定我们的特性可以用在什么地方
    // 默认特性可以用在所有的地方
    // Method   方法
    // Property 属性
    // Constructor  构造函数
    // Field    字段
    // Class    类
    [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Constructor | AttributeTargets.Field | AttributeTargets.Class )]
    public class ABCAttribute : Attribute
    {

    }
}
//------------------------------------------------
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _06_自定义特性
{
    internal class Program
    {
        static void Main(string[] args)
        {
        }
    }

    // [ABCAttribute]
    [ABC]       // 简化
    // 构造方法中要求的参数直接写,非构造方法要求的参数  xxxx = xxxx  的格式书写
    [BugFix("老王", "2023-10-21", Description = "修复了一个不执行的bug")]
    class Test
    {
        // 19行这种写法类似于类实例化时
        // new BugFixAttribute("老王", "2023-10-21")
        // {
        //     Description = "修复了一个不执行的bug"
        // }
    }
    [BugFix("老李", "2023-11-23")]
    [Laoguo(1, B = "B的值")]
    class People
    {

    }





    [ABC]
    class A
    {
        [ABC]
        private int x;
        [ABC]
        public int MyProperty { get; set; }
        [ABC]
        public void Fn() { }
        [ABC]
        public A()
        {
            
        }
    }
}

特性的应用

C# 复制代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace _02_特性
{
    internal class Program
    {
        static void Main(string[] args)
        {
            Type t = typeof(Peolpe);

            // 反射的作用就是用来读取类型上的一些元数据
            Console.WriteLine(t.Name);  // 类名
            Console.WriteLine(t.FullName);  // 完全限定名
            Console.WriteLine(t.Namespace); // 命名空间


            // 特性就是给C#的元素添加了一些其他的信息(元数据)
            // GetCustomAttributes      获取元素上所有的特性
            // 参数:如果只传递一个Bool值,表示是否要获取该类继承自别的类的特性
            var b1 = typeof(A).GetCustomAttributes(true);   // 1个特性
            var b2 = typeof(A).GetCustomAttributes(false);  // 0个特性
            // 另一个重载,用于筛选我们要获取该元素上的哪些特性
            // 参数1:你要获取哪个类型的特性
            // 参数2:传递一个Bool值,表示是否要获取该类继承自别的类的特性
            var b3 = t.GetCustomAttributes(typeof(EfgAttribute), false);
            var b4 = t.GetCustomAttributes(typeof(BugFixAttribute), false);


            // 获取某一个特性
            Attribute attribute = t.GetCustomAttribute(typeof(BugFixAttribute));
            Console.WriteLine("t这个类型拥有特性BigFix,修改该bug的人是:" + (attribute as BugFixAttribute).Name);


            // 练习:获取People类型上的属性bug修复情况
            // 1、先获取所有的属性
            foreach (PropertyInfo p in t.GetProperties())
            {
                // 2、获取该属性的 BugFixAttribute 特性
                Attribute att = p.GetCustomAttribute(typeof(BugFixAttribute));
                // 3、如果有该特性,则输出即可
                if(att != null)
                {
                    Console.WriteLine($"{p.Name}属性被修复,修改人:{(att as BugFixAttribute).Name}");
                }
            }


            Console.ReadKey();
        }
    }

    // 使用该特性
    [BugFix("张三")]
    [Efg]
    [Efg]
    [Efg]
    class Peolpe
    {
        [BugFix("王五")]
        public int MyProperty1 { get; set; }
        [BugFix("王五")]
        public int MyProperty2 { get; set; }
        public int MyProperty3 { get; set; }
    }

    // 创建了一个自定义特性
    class BugFixAttribute : Attribute
    {
        public string Name { get; set; }
        public BugFixAttribute(string name)
        {
            Name = name;
        }
    }

    // Inherited    如果为true,则使用了该特性的类的子类也会继承该特性(如下例中 A 类同样会拥有 B 类的特性)
    [AttributeUsage(AttributeTargets.All, Inherited = true)]
    class AbcAttribute : Attribute { }

    [AttributeUsage(AttributeTargets.All, AllowMultiple = true)]
    class EfgAttribute : AbcAttribute { }

    [Abc]
    class B { }
    class A : B { }

}
//===================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace _03_特性使用练习
{
    internal class Program
    {
        static void Main(string[] args)
        {
            Test.BugLog<People>();


            Console.ReadLine();
        }
    }
    [BugFix("张三", "2023-10-22", "测试一下")]
    class People
    {
        [BugFix("张三", "2023-10-22", "测试一下")]
        public int MyProperty { get; set; }
        public int MyProperty1 { get; set; }
        [BugFix("张三", "2023-10-22", "测试一下")]
        public void Fn()
        {

        }
        public void Fn1()
        {

        }
    }
    class Test
    {
        public static void BugLog<T>()
        {
            // 输出参数T所包含的所有bugFix特性的信息
            // 1、根据参数生成 Type
            Type t = typeof(T);
            // 2、先看这个类有没有该特性
            WriteInfo(t, "类");

            // 如:xxxx方法: xx年xx月xx日xxx修复,bug描述:xxxxxx
            // 4、循环方法
            foreach (MethodInfo v in t.GetMethods())
            {
                WriteInfo(v, "方法");
            }

            // 如:xxxx属性: xx年xx月xx日xxx修复,bug描述:xxxxxx
            foreach(PropertyInfo v in t.GetProperties())
            {
                WriteInfo(v, "属性");
            }
        }
        private static void WriteInfo(MemberInfo t, string text)
        {
            Attribute attr = t.GetCustomAttribute(typeof(BugFixAttribute));
            BugFixAttribute attr2 = (BugFixAttribute)attr;
            // 3、判断并输出
            if (attr != null)
            {
                Console.WriteLine($"{t.Name}{text}: {attr2.Time}{attr2.Name}修复,bug描述:{attr2.Message}");
            }
        }
    }
    class BugFixAttribute : Attribute
    {
        public string Name { get; set; }
        public string Time { get; set; }
        public string Message { get; set; }
        public BugFixAttribute(string name, string time, string message)
        {
            Name = name;
            Time = time;
            Message = message;
        }
    }
}
相关推荐
只待花开1 小时前
QT5.12.9 通过MinGW64 / MinGW32 cmake编译Opencv4.5.1
开发语言·qt
我写代码菜如坤1 小时前
C#中Stopwatch的使用
开发语言·c#
wjs20242 小时前
SQLite Glob 子句
开发语言
MarkHD5 小时前
javascript 常见设计模式
开发语言·javascript·设计模式
海盗猫鸥5 小时前
C++入门基础篇(1)
开发语言·c++·学习
专注成就自我5 小时前
java使用easypoi模版导出word详细步骤
java·开发语言·word
多多*6 小时前
SpringBoot 启动流程六
java·开发语言·spring boot·后端·spring
让你三行代码QAQ6 小时前
SpringSecurity初始化过程
java·开发语言
Mr_Richard6 小时前
Java动态代理的实现方式
java·开发语言
码农超哥同学7 小时前
Python面试题:请解释 `lambda` 函数是什么,并举一个例子
开发语言·python·面试·编程