C# 反射:Reflection用法速通

常用类一览

类名

实例方式

用途

Assembly

程序集类


Assembly <Name> = Assembly.loadFrom("Path");

左侧代码调用了Assembly类的静态函数loadFrom通过查找文件地址返回程序集对象(Assembly对象)

Type

类型类


Type <Name> = <AssemblyObj>.GetType("Type Name");

左侧代码调用了Assembly类的函数GetType通过查找成员名返回Type对象

MethodInfo

函数信息类


MethodInfo <Name> = <TypeObj>.GetMethod("FuncName");

左侧代码调用了Type类的函数GetMethod通过查找函数名返回MethodInfo对象

PropertyInfo

属性信息类


PropertyInfo <Name> = <TypeObj>.GetProperty("PropertyName");

左侧代码调用了Type类的函数GetProperty通过查找属性名返回PropertyInfo对象

FieldInfo

字段信息类


FieldInfo <Name>=<TypeObj>.GetField("Field Name");

左侧代码调用了Type类的函数GetField通过查找属性名返回FieldInfo对象

BindingFlags

筛选标志

枚举类型

通常用于检索条件/调用标识

专有名词解析

Assembly类型解析


using Reflection;//用于引入反射包

/*   Assembly常用API
//通过路径返回程序集对象
Assembly.LoadFrom("Path"); return:AssemblyObj;

//返回程序集对象里的所有类型(类/结构体... ...)
<AssemblyObj>.GetTypes(); return:TypeObj[];

//通过类型名字(TypeName)进行查找然后返回
<AssemblyObj>.GetType("TypeName"); return:TypeObj;
    -->:<AssemblyObj>.GetType("TypeName`int");//用于查找泛型类 其中[`int]:`为必带的,int为泛型的数量
    -->:TypeName的结构必须是 NameSpace.Class

//返回包含程序入口点的程序集  
Assembly.GetEntryAssembly(); return:AssemblyObj;

//返回当前代码执行的程序集
Assembly.GetExecutingAssembly(); return:AssemblyObj;

//返回当前代码执行的程序集
<AssemblyObj>.GetExecutingAssembly(); return:AssemblyObj;

//将类型实例化成具体的对象
<AssemblyObj>.CreateInstance("TypeName“);  return:Object;     TypeName:命名空间.类型名

*/

/*   Assembly常用成员属性
//获取程序集的完全限定名
<AssemblyObj>.FullName;+ return:String; 

//获取程序集的文件绝对路径
<AssemblyObj>.Location; return:String;

//获取程序集合入口方法
<AssemblyObj>.EntryPoint; return:MethodInfo;

//判断程序集是否在全局缓存中
<AssemblyObj>.GlobalAssemblyCache; return:Bool;

//获取程序集的代码库位置 不带转义符
<AssemblyObj>.CodeBase; return:String;

//获取程序集的代码库位置 带转义符
<AssemblyObj>.EscapedCodeBase; return:String;

//获取程序集的CLR版本
<AssemblyObj>.ImageRuntimeVersion; return:String;

//获取程序集的清单模块
<AssemblyObj>.MannifestModule; return:RuntimeModule;

//判断程序集是否只能用于反射上下文
<AssemblyObj>.ReflectionOnly; return:Bool;

//判断程序集是否是动态程序集
<AssemblyObj>.IsDynamic; return:Bool;
*/

Type类型解析


using System;//Type类型必备的包

/*Type类型常用API

//返回Type类型   对一个类型做两次GetType的返回值不一样
<TypeObj>.GetType(Object); 第一次return:Type; 第二次return:RuntimeType;

//返回Type的枚举类型  其实就是方便识别的类型比如String/Int等
<TypeObj>.GetTypeCode(); return:TypeCode;

//用于直接调用成员
<TypeObj>.InvokeMember("MemberName",<BindingFlags.Enum>,<Binder>,<InstanceObject>,new object(<args>...));
    -->:MemberName:成员名 主要看后面筛选规则是什么
    -->:BindingFlags.Enum:BindingFlags枚举类型,用于限制查找条件
        -->:InvokeMember除了条件BindingFlags以外必须带有一个特殊的BindIngFlags
        -->:InvokeMember去实例对象时除了BindingFlags.CreateInstance以外不要带其他BindingFlags
    -->:Binder:很高级我不会,所以一般都填null
    -->:InstanceObject:具体调用这个函数的对象,若是静态函数则填null
    -->:new object(<args>...):调用函数的传参 比如调用一个func(int temp_1,string temp_2)的函数
        -->:则为 new object(Int,String);

//判断Obj是否是TypeObj类的实例化对象
<TypeObj>.IsInstanceOfType(Obj); return:Bool;

//判断TypeObj2是否是TypeObj的 派生类(子类)
<TypeObj>.IsSubclassof(TypeObj2); return:Bool;

//与特性相关  判断类型是否拥有特性   <AttributeClass Class>:特性类  <Bool Inherit>:true则查找继承链,false不查找
<TypeObj>.IsDefined( typeof(<AttributeClass Class>) , <Bool Inherit>); return:Bool;

//Make方法汇总 用于创建Type对象
<TypeObj>.MakeArrayType(Int); Int可选; return:Type;     //创建一个TypeObj的数组类型
<TypeObj>.MakeGenericType(typeof(<类型>)...); return:Type               //创建一个泛型类型的Type对象
<TypeObj>.MakeByRefType(); return:Type                 //创建一个引用类型的Type对象


//Get函数方法汇总 用于获取内容(成员)
<TypeObj>.GetElementType(); return:Type;               //若TypeObj是数组类型,则返回数组的元素类型

<TypeObj>.GetField("FieldName"); return:FieldInfo;     //通过FieldName获取字段
    -->:<TypeObj>.GetField("FieldName",<BindingFlags.Enum>);
    -->:<TypeObj>.GetFields(); return:FieldInfo[];             //获取所有字段

<TypeObj>.GetInterface("InterFaceName"); return:Type;  //通过检索InterFaceName获取类型所实现的接口
    -->:<TypeObj>.GetInterfaces(); return:Type[];              //获取类型所实现的所有接口

<TypeObj>.GetMethod("MethodName"); return:MethodInfo;  //通过MethodName获取函数
    -->:<TypeObj>.GetMethod("MethodName",new object(<Args>...));//带参数的获取方法
    -->:<TypeObj>.GetMethod("MethodName",<BindingFlags.Enum>,new object(<Args>...));
    -->:<TypeObj>.GetMethods(); return:MethodInfo[];           //获取所有函数
    //获取静态的非公开的函数
    -->:<TypeObj>GetMethod("MethodName",BindingFlags.Static|BindingFlags.NonPublic);

<TypeObj>.GetProperty("PropertyName"); return:PropertyInfo; //通过PropertyName获取属性
    -->:<TypeObj>.GetProperty("PropertyName",<BindingFlags.Enum>);
    -->:<TypeObj>.GetProperties(); return:PropertyInfo[];       //获取所有Property组成的数组

<TypeObj>.GetConstructor(new Type[]{typeof(<类型1>)...}); return:ConstructorInfo;
    //根据参数传类型 返回构造函数
    -->:<TypeObj>.GetConstructors(); return:ConstructorInfo[]; //返回所有构造函数组成的数组

<TypeObj>.GetCustomAttributes(typeof(<AttributeClass Class>,<Bool inherit>));
    //return:object  可以通过as转换为类
    //查找当前类型所加载的所有指定特性    <AttributeClass>:指定特性    <Bool Inherit>:是否查找根目录
    //查找到的同时将其构造出来

*/

/*Type类型常用属性

<TypeObj>.AssemblyQualifedName; //获取类型在程序集的完全限定名
<TypeObj>.Assembly;             //获取包含类型的程序集对象本身
<TypeObj>.Attributes;           //获取类型的自定义特性
<TypeObj>.BaseType;             //获取类型的基(父)类型
<TypeObj>.ContainsGemericParameters; //判断类型是否存在未指定的泛型参数
<TypeObj>.DeclaringMethod;      //获取声明类型的方法
<TypeObj>.DeclaringType;        //获取声明类型的类型\
<TypeObj>.FullName;             //获取类型的完全限定名
<TypeObj>.GenericParameterAttributes; //获取泛型类型参数的特性
<TypeObj>.GenericParameterPosition;   //获取泛型类型参数在类型参数列表中的位置
<TypeObj>.GUID;                 //获取类型的GUID
<TypeObj>.HasElementType;       //判断类型是否是数组/指针/引用

//Is属性汇总  return:Bool
<TypeObj>.IsAbstract;           //判断是否为抽象的
<TypeObj>.IsArray;              //判断是否为数组
<TypeObj>.IsByRef;              //判断是否为引用类型
<TypeObj>.IsClass;              //判断是否为类或者委托(即:不是接口或者值类型等)
<TypeObj>.IsEnum;               //判断是否为枚举类型
<TypeObj>.IsGenericParameter;   //判断是否为泛型类型参数
<TypeObj>.IsGenericType;        //判断是否为泛型类型
<TypeObj>.IsInterface;          //判断是否为接口
<TypeObj>.IsNested;             //判断是否为嵌套类型
<TypeObj>.IsNotPublic;          //判断是否不是公共的 且 并不在同一程序集中
<TypeObj>.Isprimitive;          //判断是否为基元类型
<TypeObj>.IsPublic;             //判断是否为公共类型
<TypeObj>.IsSealed;             //判断是否为密封类型     带关键词:Sealed的类,指无法被继承
<TypeObj>.IsSerializable;       //判断是否为可序列化的
<TypeObj>.IsValueType;          //判断是否为值类型

//不常用的
<TypeObj>.IsAutoClass;          //判断是否为自动类
<TypeObj>.IsAutoLayout;         //判断是否为自动布局的
<TypeObj>.IsAnsiClass;          //判断是否为使用ANSI标准的类
<TypeObj>.IsContextful;         //判断是否为上下文相关的泛型类型
<TypeObj>.IsImport;             //判断是否为COM类型库导入的类型
<TypeObj>.IsLayoutSequential;   //判断是否为顺序布局
<TypeObj>.IsMarshalByRef;       //判断是否由MarshalByRefObject派生的类
<TypeObj>.IsSecuritySafeCritical;//判断是否为安全关键类型
<TypeObj>.IsSpecialName;        //判断是否存在特殊名称
<TypeObj>.IsUnicodeClass;       //判断是否满足Unicode标准的类
<TypeObj>.IsGenericTypeDefinition;//判断是否为泛型类型的定义  即:typeof(List<>)而非typeof(List<类型>)
<TypeObj>.IsConstructedGenericType;//判断是否为已构造的泛型类型   即:typeof(List<类型>)而非typeof(List<>)
<TypeObj>.IsVisible;            //判断是否为公共或者嵌套类型 一个类型是否对当前程序集可见



*/

MethodInfo类型解析


/*MethodInfo解析     <MethodInfo>转换<Info>


//MethodInfo属性
<Info>.MemberType;            //获取MemberType值,用于指示这个成员是方法
<Info>.MethodHandle;          //获取RuntimeMethodHandle,用于表示内部的元数据类型
<Info>.MethodImplementationFlags;//获取MethodImplAttributes值,该值指示此方法的实现标志
<Info>.Name;                  //此方法的名词
<Info>.ReflectionType;        //获取此方法的类对象
<Info>.ReturnType;            //获取方法的返回类型
<Info>.ReturnTypeCustomAttributes;//获取包含返回类型的自定义属性
<Info>.CallingConventionl     //获取此方法的调用约定

//Is判断内容
<Info>.IsAbstract;            //判断是否为抽象的                    
<Info>.IsAssembly;            //判断是否只能由内部程序集访问         
<Info>.IsConstructor;         //判断是否为构造函数                  
<Info>.IsFamliy;              //判断是否只能有类或者子类的对象调用     
<Info>.IsFamliyAndAssembly;   //判断既属于程序集又属于类的对象调用
<Info>.IsFamliyAndAssembly;   //判断是否属于程序集或者指定类的对象调用     
<Info>.IsFinal;               //判断是否为Final方法                 
<Info>.IsGenericMethod;       //判断是否为泛型类型
<Info>.IsHideBySig;           //判断是否隐藏继承的成员
<Info>.IsPrivate;             //判断是否为私有函数
<Info>.IsPublic;              //判断是否为共有函数
<Info>.IsSpecialName;         //判断是否存在特殊名称
<Info>.IsStatic;              //判断是否静态方法
<Info>.IsVirtual;             //判断是否为虚方法
*/

/*MethodInfo  API函数
<Info>.GetParameters();       //获取方法的参数列表  只能获取一个函数 若存在多个函数则会报错
<Info>.GetCustomAttribute(type(<Attribute>));            //获取特性

<Info>.Invoke(Object,new object[]{Parameter... ...}); //调用函数     Invoke(具体的对象,new object[]{参数... ...})
    <Info>.Invoke(null,new object[]{Parameter... ...}); //调用静态函数 
<Info>.MakeGenericMethods(typeof(<类型1>)...);   return:MethodInfo;         //获取到方法后可以用这个调用泛型方法
    --
*/

FieldInfo解析


/*FieldInfo属性   解析   <FieldInfo>简写<Info>
<Info>.CustomAttributes;   //获取一个包含当前字段的自定义属性的集合
<Info>.Name;               //获取字段的名称。
<Info>.FieldType;          //获取字段的类型。

//Is判断内容
<Info>.IsStatic;           //获取一个值,该值指示字段是否为静态字段。
<Info>.IsPublic;           //获取一个值,该值指示字段是否为公共字段。
<Info>.IsPrivate;          //获取一个值,该值指示字段是否为私有字段。
<Info>.IsFamily;           //获取一个值,该值指示字段是否为受保护的字段。
<Info>.IsAssembly;         //获取一个值,该值指示字段是否为内部字段。
<Info>.IsFamilyOrAssembly; //获取一个值,该值指示字段是否为受保护的内部字段。
<Info>.IsInitOnly;         //获取一个值,该值指示字段是否为只读字段。
<Info>.IsLiteral;          //获取一个值,该值指示字段是否为常量字段。
<Info>.IsNotSerialized;    //获取一个值,该值指示字段是否不应序列化。
<Info>.IsPinvokeImpl;      //获取一个值,该值指示字段是否为 P/Invoke 实现。
<Info>.IsSpecialName;      //获取一个值,该值指示字段是否具有特殊名称。

*/

/*FieldInfo API

<Info>.IsDefined(Type attributeType, bool inherit);  //获取一个值,该值指示是否定义了指定类型的特性
<Info>.GetValue(<Object>);                                   //获取字段里的值
<Info>.SetValue(<Object>,<Value>);                   //向字段内写入值
*/

PropertyInfo解析


/*PropertyInfo解析   <propertyInfo>简写<Info>

//PropertyInfo属性
Property.PropeytyType;                  //获取属性的属性
Property.IsDefined(<AttributeType>,<Bool>);    //是否将一个或多个特性应用于此成员


//PropetyInfo函数
<Info>.GetValue(<Object>);            //调用属性的Get方法
<Info>.SetValue(<Object>,<Value>);    //调用属性的Set方法
<Info>.GetCustomAttributes(<Bool>);   //获取属性上定义的特性  <Bool>为True则搜索此成员的继承链以查找这些属特性 False只查找自身的
    <Info>.GetCustomAttributes(typeof(<Attribute>),<Bool>);    //查找特定特性
*/

BindingFlags解析


//BindingFlags是一个枚举类型
/*
//限制筛选规则
BindingFlags.Default;            //默认模式
BindingFlags.IgnoreCase;         //无视大小写
BindingFlags.IgnoreReturn;       //忽略函数返回值
BindingFlags.Instance;           //包含实例成员
BindingFlags.NonPublic;          //包含非公共成员
BindingFlags.Public;             //公共成员
BindingFlags.Static;             //静态成员
BindingFlags.FlattenHierarchy;   //搜索类型层次结构中的父级  ?我不理解

//调用筛选规则
BindingFlags.PutDispProperty;    //分配给Idispatch::Invoke的属性
BindingFlags.PutRefDispProperty; //分配给IDispatch::Invoke的ref属性
BindingFlags.SetField;           //Set字段
BindingFlags.SetProperty;        //Set属性
BindingFlags.GetField;           //Get字段
BindingFlags.GetProperty;        //Get属性属性
BindingFlags.ExactBinding;       //确切的绑定:只有在名称、参数类型和修饰符都完全匹配时才会返回成员
BindingFlags.InvokeMethod;       //若使用Type.InvokeMethod调用函数时,则添加这个筛选规则
BindingFlags.CreateInstance;     //用于创建实例
*/

/*常用组合搭配
Instance | Public | NonPublic:指定所有实例成员。
Static | Public | NonPublic:指定所有静态成员。
FlattenHierarchy | Public | Instance:指定搜索类型层次结构中的公共实例成员和父级。
FlattenHierarchy | Public | Static:指定搜索类型层次结构中的公共静态成员和父级。
FlattenHierarchy | Public | Instance | DeclaredOnly:指定搜索类型层次结构中的公共实例成员和父级,但仅在当前类型中查找成员,而不搜索基类型。
*/

专有名词解析


/*基元类型
bool:表示布尔值。
byte:表示8位无符号整数。
sbyte:表示8位有符号整数。
char:表示16位 Unicode 字符。
decimal:表示高精度小数。
double:表示64位浮点数。
float:表示32位浮点数。
int:表示32位有符号整数。
uint:表示32位无符号整数。
long:表示64位有符号整数。
ulong:表示64位无符号整数。
short:表示16位有符号整数。
ushort:表示16位无符号整数
*/

/*实例成员
实例成员是指只能通过类的实例来访问的成员,而不能通过类名来访问。
实例成员包括实例字段、实例属性、实例方法和实例事件。
可以使用BindingFlags.Instance标志来获取实例成员。
*/

/*字段
int <name> = <Value>;
这就是一个字段
*/

/*属性
int <PropertyName>={
set{代码块}
get{代码块}
}
这就是一个属性
*/

小案例

准备工作

先创建一个文件里面包含两个类,随后将其生成为dll文件


namespace{
//写一个接口IUtil 权限为public 拥有一个函数String Func()
    public interface IUtil
    {
        string TestFunc();
    }

//再写一个UtilPackage类,实现了IUtil
    public class UtilPackage:IUtil
    {
        public string TestFunc()
        {
            Console.WriteLine("TestFunc无参");
            return "TestFUnc";
        }
    }
}

此时将其文件路径复制,博主这边dll文件路径位置为F:\C#学习\C# item\Util\bin\Debug\Util.dll


using System;
using Reflection;//反射必备的命名空间
namespace
{
    internal class Program{
        private static void Main(string[] args)
        {
            //利用Assembly
            Assembly assembly = Assembly.LoadFrom(@"F:\C#学习\C# item\Util\bin\Debug\Util.dll");
        }
    }
}

引入Reflection反射包;using Reflection;

第一阶段:利用反射调用dll文件里的函数TestFunc


using System;
using System.Reflection;//反射必备的命名空间
namespace
{
    internal class Program{
        private static void Main(string[] args)
        {
            //通过Assembly的API:LoadFrom获取到程序集对象
            Assembly utilAss = Assembly.LoadFrom(@"F:\C#学习\C# item\Util\bin\Debug\Util.dll");
            //通过Assembly的API:GetType获取UtilPackage的类型Type
            Type utilPackageType = utilAss.GetType("Util.UtilPackage");
            //通过Assembly里的API:CreateInstance("MemberName");去实例一个对象
            object utilPackageObj = utilAss.CreateInstance("Util.UtilPackage");
                //对于这一步也可以用Activator.CreateInstance(<Type>)去创建对象
                //例如:object UtilPackageObj = Acitivator.CreateInstance(utilPackageType);
            //通过Type里的API:GetMethod("MethodName")获取到了具体的函数对象
            MethodInfo textFunc = utilPackageType.GetMethod("TestFunc");
            //调用MethodInfo类的API:Invoke(<Object>,<Parameter>)去执行函数
            //MethodInfo.Invoke(<实例对象>,<参数>);注意参数要用new object去传输
            testFunc.Invoke(utilPackageObj, new object[] { });
        }
    }
}

当读者去执行这块代码时,输出的结果为:TestFunc无参

第二阶段:利用反射调用重载方法

将原UtilPackage小做修改


namespace Util{
//写一个接口IUtil 权限为public 拥有一个函数String Func()
    public interface IUtil
    {
        string TestFunc();
    }

//再写一个UtilPackage类,实现了IUtil
    public class UtilPackage:IUtil
    {
        //原TestFunc
        public string TestFunc()
        {
            Console.WriteLine("TestFunc无参");
            return "TestFUnc";
        }
        //重载TestFunc函数
        public string TestFunc(String temp_i)
        {
            Console.WriteLine("TestFunc|参数1:String="+temp_i);
            return "TestFUnc";
        }
        //重载TestFunc函数
        public string TestFunc(String temp_i,int temp_j)
        {
            Console.WriteLine("TestFunc|参数1:String="+temp_i+"|参数2:int="+temp_j);
            return "TestFUnc";
        }
    }
}

回到主要函数Main来


using System;
using System.Reflection;//反射必备的命名空间
namespace
{
    internal class Program{
        private static void Main(string[] args)
        {
            //通过Assembly的API:LoadFrom获取到程序集对象
            Assembly utilAss = Assembly.LoadFrom(@"F:\C#学习\C# item\Util\bin\Debug\Util.dll");
            //通过Assembly的API:GetType获取UtilPackage的类型Type
            Type utilPackageType = utilAss.GetType("Util.UtilPackage");
            //通过Assembly里的API:CreateInstance("MemberName");去实例一个对象
            object utilPackageObj = utilAss.CreateInstance("Util.UtilPackage");
                //对于这一步也可以用Activator.CreateInstance(<Type>)去创建对象
                //例如:object UtilPackageObj = Acitivator.CreateInstance(utilPackageType);
            //-------------------------------------------------------分割符
            //通过Type里的API:GetMethod("MethodName",<ParameterType>)获取到了具体的函数对象
            //这里才用GetMethod的重载方法
            MethodInfo testFunc1 = utilPackageType.GetMethod("TestFunc", new Type[] {});
            MethodInfo testFunc2 = utilPackageType.GetMethod("TestFunc", new Type[] {typeof(string)});
            MethodInfo testFunc3 = utilPackageType.GetMethod("TestFunc", new Type[] {typeof(string),typeof(int)});
            //MethodInfo.Invoke(<实例对象>,<参数>);注意参数要用new object去传输
            testFunc1.Invoke(utilPackageObj, new object[] { });
            testFunc2.Invoke(utilPackageObj, new object[] {"DarkSKL"});
            testFunc3.Invoke(utilPackageObj, new object[] {"DarkSKL",18});
        }
    }
}

/*//当读者去执行这篇代码时,运行结果为:
TestFunc无参
TestFunc|参数1:String=DarkSKL
TestFunc|参数1:String=DarkSKL|参数2:int=18
*/

第三阶段:通过反射调用属性以及字段,包含私有如何获取

将原UtilPackage小做修改


namespace Util
{
    public class UtilPackage : IUtil
    {
        //定义了一个name字段
        private string name = "DarkSKL";
        //以及一个只有get方法的Name属性
        public string Name
        {
            get { return name; }
        }

        public string TestFunc()
        {
            Console.WriteLine("TestFunc无参");
            return "TestFUnc";
        }
    }
}

回到主要函数Main来


using System;
using System.Reflection;//反射必备的命名空间
namespace Util
{
    internal class Program{
        private static void Main(string[] args)
        {
            //通过Assembly的API:LoadFrom获取到程序集对象
            Assembly utilAss = Assembly.LoadFrom(@"F:\C#学习\C# item\Util\bin\Debug\Util.dll");
            //通过Assembly的API:GetType获取UtilPackage的类型Type
            Type utilPackageType = utilAss.GetType("Util.UtilPackage");
            //通过Assembly里的API:CreateInstance("MemberName");去实例一个对象
            object utilPackageObj = utilAss.CreateInstance("Util.UtilPackage");
                //对于这一步也可以用Activator.CreateInstance(<Type>)去创建对象
                //例如:object UtilPackageObj = Acitivator.CreateInstance(utilPackageType);
            //-------------------------------------------------------分割符
            //注意这串代码会找不到字段name:FieldInfo nameField = utilPackageType.GetField("name");
            //如果要获取私有的,则需要用到重载方法GetField("FieldName",<BindingFlags.Enum>)
            FieldInfo nameField = utilPackageType.GetField("name",BindingFlags.NonPublic|BindingFlags.Instance);
            //通过Type类的API:GetProperty获得属性对象
            PropertyInfo nameProperty = utilPackageType.GetProperty("Name");
            //调用FieldInfo得API:GetValue(<Object>)获取值内容
            Console.WriteLine("name值为:"+nameField.GetValue(utilPackageObj));
            //调用FieldInfo得API:GetValue(<Object>)获取值内容
            Console.WriteLine("name值为:"+nameProperty.GetValue(utilPackageObj));
        }
    }
}
/*
当读者执行完代码时,输出结果为:
name值为:DarkSKL
name值为:DarkSKL
*/

第四阶段:通过反射调用泛型成员

将原UtilPackage小做修改


namespace Util
{
    //类存在一个泛型参数<T>
    public class UtilPackage<T> : IUtil
    {
        //用于保存自身类型
        private Type utilGenericType = typeof(T);
        //用于返回自身类型
        public Type UtilGenericType
        {
            get { return utilGenericType; }`
        }
        //利用<T>声明一个字段value
        private T value;
        //利用属性返回value
        public T Value
        {
            set { this.value = value;}
            get { return value; }
        }
        //重写的IUtil接口的方法
        public string TestFunc()
        {
            Console.WriteLine("TextFunc");
            return "TestFunc";
        }
        //重载TextFunc,定义了一个泛型<K>
        public object TextFunc<K>(K temp_i)
        {
            Console.WriteLine("TextFunc<K>");
            return temp_i.GetType();
        }
    }
}

回到主入口Main这边来


using System;
using System.Reflection;//反射必备的命名空间
namespace Util
{
    internal class Program{
        private static void Main(string[] args)
        {
            //通过Assembly的API:LoadFrom获取到程序集对象
            Assembly utilAss = Assembly.LoadFrom(@"F:\C#学习\C# item\Util\bin\Debug\Util.dll");
            //通过Assembly的API:GetType获取UtilPackage的类型Type  注意:这里的名称是Util.UtilPackage`1
            Type utilPackageType = utilAss.GetType("Util.UtilPackage`1");
            //将其泛型初始类具体的实例为已实例过的泛型类
            Type utilPackageType_Generic_int = utilPackageType.MakeGenericType(new Type[]{typeof(int)});
            //对于泛型类还需要用到Type的API:MakeGenericType去实例出泛型类
            //将其实例成具体的对象
            object utilPackageObj = Activator.CreateInstance(utilPackageType_Generic_int);

            //-------------------------------------------------------分割符

            //通过Type的API:GetProperty获取属性
            PropertyInfo utilPackage_ValueProperty = utilPackageType_Generic_int.GetProperty("Value");
            //同理取得UtilGenericType
            PropertyInfo utilPackage_TypeProperty = utilPackageType_Generic_int.GetProperty("UtilGenericType");
            string temp_m = utilPackage_ValueProperty.GetValue(utilPackageObj).ToString();
            string temp_n = utilPackage_TypeProperty.GetValue(utilPackageObj).ToString();
            Console.WriteLine("Value:"+temp_m+"|GenericType:"+temp_n);

            Console.WriteLine("//-------------------------------------------------------分割符" );
            //-------------------------------------------------------分割符

            //先获取方法
            MethodInfo func = utilPackageType_Generic_int.GetMethod("TextFunc");
            //再将方法转为泛型方法
            func = func.MakeGenericMethod(new Type[] { typeof(int) });
            //调用TextFunc并将返回值输出
            Console.WriteLine(func.Invoke(utilPackageObj, new object[] { 1}));

            }
    }
}
/*
当读者执行完代码时,输出结果为:
Value:0|GenericType:System.Int32

TextFunc<K>
System.Int32
*/

第五阶段:通过反射获取泛型(独立)


     #region 实体逻辑特性类 
/// <summary>
    /// 特性:实体逻辑类   用于标注这是一个逻辑函数
    /// </summary>
    [AttributeUsage( AttributeTargets.Method, Inherited = true, AllowMultiple = false)]
    public sealed class LogicAttribute : Attribute
    {

        #region Field
        /*字段注释
         *name:逻辑名称
         *note:逻辑注释
         *index:逻辑序号
         */
        private string name;
        private string note;
        private int    index;
        #endregion

        #region Property
        /// <summary>
        /// 逻辑的名称
        /// </summary>
        public string Name =>  name;
        /// <summary>
        /// 逻辑的注释
        /// </summary>
        public string Note =>  note;
        /// <summary>
        /// 逻辑的序号
        /// </summary>
        public int    Index => index;
        #endregion

        #region Constructor

        /// <summary>
        /// 构造函数:初始化逻辑特性
        /// </summary>
        public LogicAttribute(string _Name,string _Note,int _Index)
        {
            this.name  =  _Name;
            this.note  =  _Note;
            this.index =  _Index;
        }
        #endregion

    }

    #endregion

    #region 实体逻辑模块

    public abstract class Logic
    {
        #region Field

        /*字段注释
         * Name :逻辑名称
         * index:逻辑状态标识
         * logic:逻辑函数主体   状态标识:(逻辑名称,逻辑特性,逻辑函数)
         */
        protected string name;
        protected int    state;
        protected Dictionary<int,Tuple<string,LogicAttribute,MethodInfo>> logic;
        #endregion

        #region Property
        /// <summary>
        /// 逻辑名称
        /// </summary>
        public string Name  => this.name;
        /// <summary>
        /// 逻辑状态标识
        /// </summary>
        public int    State => this.state;
        #endregion

        #region Constructor
        /// <summary>
        /// 构造函数:初始化逻辑的名称以及状态还有逻辑的函数
        /// </summary>
        /// <param name="_Name">逻辑总体名称</param>
        /// <param name="_State">逻辑状态,默认为1</param>
        protected Logic(string _Name,int _State = 1)
        {
            this.name  = _Name;
            this.state = _State;
            //将其实例化
            logic = new Dictionary<int, Tuple<string, LogicAttribute, MethodInfo>>();
            //获取自身类型对象
            Type type = this.GetType();
            //查找自身函数标注了LogicAttribute特性的函数
            MethodInfo[] methods =
                type.GetMethods().Where(p => p.IsDefined(typeof(LogicAttribute))).ToArray();
            for (int i = 0; i < methods.Length;i++)
            {
                //获取逻辑函数上标注的特性
                LogicAttribute logicattribute =
                    methods[i].GetCustomAttribute(typeof(LogicAttribute),true)
                        as LogicAttribute;
                //创建一个元组,用于存放
                Tuple<string,LogicAttribute, MethodInfo> temp_Tuple = new Tuple<string, LogicAttribute, MethodInfo>(logicattribute.Name,logicattribute, methods[i]);
                        //测试
                        //Console.WriteLine(temp_Tuple);
                //将其添加进逻辑函数字典中
                logic.Add(logicattribute.Index,temp_Tuple);
            }
        }
        #endregion

        #region Method
        /// <summary>
        /// 函数:执行
        /// </summary>
        public abstract void Invoke();
        /// <summary>
        /// 函数:移除
        /// </summary>
        public abstract void Remove();
        #endregion
    }

    public class TestLogic : Logic
    {
        public TestLogic(string _Name, int _State = 1) : base(_Name, _State)
        {
            Console.WriteLine("测试用的逻辑");
        }


        public override void Invoke()
        {
            foreach (var temp in logic)
            {
                Console.WriteLine(temp);
            }
        }

        public override void Remove()
        {
            Console.WriteLine("执行了Remove函数");
        }

        [Logic("测试函数","专门用来测试的函数",1)]
        public void func()
        {
            Console.WriteLine("执行了测试函数");
        }
        [Logic("测试函数1", "专门用来测试的函数", 2)]
        public void func1()
        {
            Console.WriteLine("执行了测试函数");
        }
        [Logic("测试函数2", "专门用来测试的函数", 3)]
        public void func2()
        {
            Console.WriteLine("执行了测试函数");
        }
        [Logic("测试函数3", "专门用来测试的函数", 4)]
        public void func3()
        {
            Console.WriteLine("执行了测试函数");
        }
    }

    private static void Main(string[] args)
        {
            Logic logic = new TestLogic("测试用");
            logic.Invoke();
        }


/*
输出结果
测试用的逻辑
[1, (测试函数, Entity.LogicAttribute, Void func())]
[2, (测试函数1, Entity.LogicAttribute, Void func1())]
[3, (测试函数2, Entity.LogicAttribute, Void func2())]
[4, (测试函数3, Entity.LogicAttribute, Void func3())]
*/

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值