泛型和反射

王朝学院·作者佚名  2016-08-27
窄屏简体版  字體: 小  |  中  |  大  |  超大  

泛型和反射经常是一起工作的,所以就一次介绍吧.

c# 是强类型语言,一般上函数的返回类型和参数的类型都是一早些好的,也就造成了很多时候不像js那样方便使用,不灵话。

所以呢就有了这个泛型,它可以让你的函数和参数在调用的时候才决定类型。

publicT abc<T>(TWord)

{returnword;returndefault(T);//关键字default可以对引用类型返回nullAble,int类型返回0,初始化一个T的感觉啦

//return (T)Convert.ChangeType(obj1, typeof(T)); 强转}

abc<string>("x");//struct 是 值类型//好处调用的是如果参数是值类型可以不用著名 test(100) 而不需要 test<int>(100);publicvoidtest<T>(T number)whereT :struct{intz =Convert.ToInt32(number);//调用 test(100);}//下面的不知道好处在哪用在什么地方,publicvoidtest2<T>(T lei)whereT :class{

}publicvoidtest3<T>()whereT : stooges

{

}publicT test4<T>()whereT :new()

{

T abc=newT();returnabc;

}publicclassstooges

{

}

加了where 我就不清楚在什么地方用的上了,这个以后再研究

反射能让我们的代码运行时动态的获取一些对象或者类的属性值等等,甚至是调用它们。

先来一个常用到的,我们想获取一个对象的全部属性和值, 用js 是 for(var attr in object) { object[attr]=value, attr = attr }

varobj =newabc();

Type T=typeof(abc);//typeof(Class) 而不是 typeof(object) 哦Type V = obj.GetType();//obj.GetType() 就是typeof(object的class)PRopertyInfo[] attrs = obj.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public);//获取attrsforeach(PropertyInfo attrinattrs)

{stringkey = attr.Name;//获取attr nameobjectvalue = attr.GetValue(obj,null);//获取value

Type type = attr.PropertyType; //类型}

关键就是那个 Type , 获取Type后就可以做很多了

常用的方法

T.GetProperty("key").GetValue(obj,null);//read a key valueT.GetProperty("key").SetValue(obj,"",null);//write a value to key//注意如果是字典T.GetProperty("Item").GetValue(obj,new[] {"id"});//先拿Item 然后才通过 new[] {这里放指定的key}

再来看看更详细的

classMyClass

{publicintx {get;set; }publicinty {get;set; }publicMyClass(inti)

{

x= y +i;

}publicMyClass(inti,intj)

{

x=i;

y=j;

}publicintsum()

{returnx +y;

}

}

我们想获取这个Class 的构造函数

Type t =typeof(MyClass);

ConstructorInfo[] constructors= t.GetConstructors();//使用这个方法获取构造函数列表for(inti =0; i < constructors.Length; i++)

{

ConstructorInfo constructor=constructors[i];//构造函数也是方法所以有 GetParametersParameterInfo[] parameters = constructor.GetParameters();//获取当前构造函数的参数列表stringparaTypeName = parameters[0].ParameterType.Name;//方法的参数类型名称stringparaName = parameters[0].Name;//方法的参数名}//调用构造函数object[] args =newobject[2];

args[0] =10;

args[1] =20;//不用new 直接实例化objectinstance = constructors[0].Invoke(args);//实例化一个这个构造函数有两个参数的类型对象,如果参数为空,则为null

object instance = (t)Activator.CreateInstance(t); 还有这种实例的方法,不清楚可以放参数没有

调用方法

MethodInfo[] methods = T.GetMethods(BindingFlags.Public | BindingFlags.DeclaredOnly |BindingFlags.Instance);foreach(MethodInfo methodinmethods)

{stringreturn_name = method.ReturnType.Name;//返回方法的返回类型stringname =method.Name;if(name.Equals("sum", StringComparison.Ordinal))//指定方法名调用{intvalue = (int)method.Invoke(instance,null);//instance是之前实例好的对象,方法就是在这个对象之中}

}

有时想知道一个类是不是接口,或者是否实现了某个接口可以这样子

publicinterfaceIgetStringAble

{stringgetString();

}publicclasssomeClass : IgetStringAble

{publicstringgetString()

{return"";

}

}protectedvoidPage_Load(objectsender, EventArgs e)

{varobj =newsomeClass();

Type type=obj.GetType();

Type interface_=typeof(IgetStringAble);boolis_interface =interface_.IsInterface; //还有很多类型可以is的boolisThisImplementsThatInterface =interface_.IsAssignableFrom(type); //这里interface要放前面哦

}

下面是一些参考

Type t =typeof(MyClass);

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

MethodInfo[] methods=t.GetMethods();foreach(MethodInfo methodinmethods)

{

Console.WriteLine("Method:"+method);//Console.WriteLine(method);//Console.WriteLine("返回值:" + method.ReturnParameter);}

Console.WriteLine("---------------Field-------------------");//字段 ,比如这种 private static string name;FieldInfo[] fields = t.GetFields(BindingFlags.NonPublic | BindingFlags.Instance |BindingFlags.Static);foreach(FieldInfo fieldinfields)

{

Console.WriteLine("Field:"+field);

}

Console.WriteLine("--------------Member--------------------");//成员即方法和属性MemberInfo[] members =t.GetMembers();foreach(MemberInfo memberinmembers)

{

Console.WriteLine("Member:"+member);

}

Console.WriteLine("--------------Property--------------------");//属性PropertyInfo[] properties =t.GetProperties();foreach(PropertyInfo propertyinproperties)

{

Console.WriteLine("Property:"+property);

}

Console.WriteLine("--------------Constructor--------------------");//构造函数ConstructorInfo[] constructors = t.GetConstructors(BindingFlags.NonPublic |BindingFlags.Instance);foreach(ConstructorInfo constructorinconstructors)

{

Console.WriteLine("Constructor:"+constructor);

}

调用不用记太清楚,主要知道什么东西可以用反射获取和调用就可以了。

比较长使用的地方是用泛型写方法的时候,比如我们的泛型是一个不确定的类,然后我们要获取attr值等等的,就很好可以使用反射了。

还有通过string来调用方法,这个在js很长用到,比如 obj["methodName"](); 这里也可以用到反射来实现。

p.s : 反射的性能是很慢的,也可以说动态就是慢,这个很正常啦,反射的性能优化可以参考使用动态编程之类的,不过这里就不提先啦。

反射-泛型-扩展方法 小笔记

publicclassAbcd

{

}publicstaticclassExten

{publicstaticstringgetxx<T>(thisAbcd obj, Func<T,bool>deg)

{return"xx";

}publicstaticstringgetxx<T>(thisAbcd obj, Func<T,bool,int>deg)

{return"xx";

}

}

Type typeAbcd =typeof(Abcd);

Type typeExten=typeof(Exten);

IEnumerable<MethodInfo> methods = typeExten.GetMethods().Where(m => m.Name =="getxx");//当方法重载的时候,或许我们得判断它们的泛型来选择我们要的方法foreach(MethodInfo methodinmethods)

{//一个方法理应先注入类型才能调用//注入泛型的类型,一次可以多个,将返回新methodMethodInfo newMethod = method.MakeGenericMethod(newType[] {typeof(string) });//获取泛型的类型,如果还没有注入的话,这里拿到的Type Name 将会是我们匿名的名字,比如 "T"IEnumerable<Type> args = method.GetParameters()[1].ParameterType.GetGenericArguments();

}

Type func=typeof(Func<>);

func.MakeGenericType(newType[] {typeof(string),typeof(bool) });//注入类型可以这样//最终调用:MethodInfo finalMethod = methods.First().MakeGenericMethod(typeof(string));

Func<string,bool> xzzz =delegate(stringa) {returntrue; };//记住哦这是个静态方法,所以第一个参数是null,params的第一个才是实例.finalMethod.Invoke(null,newobject[] {newAbcd(), xzzz });

注:

-当有重载方法是可能需要通过它们的泛型来做选择

-方法有泛型必须先注入好类型才能调用.

-获取还没注入的泛型,返回Type,但是name是我们的匿名 比如 : <TGG> 的话就是 "TGG"

-扩展方法调用时,实例是放进第二个参数里的.

用 string 从 Assembly 获取到Class

/*DLL Reflection*///get running assemblyAssembly ass1 =Assembly.GetExecutingAssembly();//load dll , web config need got reference//get inside appcode .cs Class (appcode maybe no need set config)Assembly ass2 = Assembly.Load("App_Code.6hckh19v, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null");//Assembly ass3 = Assembly.LoadFrom("antlr3.runtime.dll");//load by path, don use betterAssembly[] assAll = AppDomain.CurrentDomain.GetAssemblies();//get all assembly/*Class Reflection*///4 ways get Type//get type by AssemblyQualifiedName , first parameter is namespace+className//use normal get Class type see the AssemblyQualifiedName 1stType type1 = Type.GetType("reflection_Default+DemoClass, App_Web_d234vjrv, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null");

Type type2=typeof(DemoClass);

Type type3=newDemoClass().GetType();

Type[] types= ass1.GetTypes();//get Class form assembly/*Type类的属性:

Name 数据类型名

FullName 数据类型的完全限定名(包括命名空间名)

Namespace 定义数据类型的命名空间名

IsAbstract 指示该类型是否是抽象类型

IsArray 指示该类型是否是数组

IsClass 指示该类型是否是类

IsEnum 指示该类型是否是枚举

IsInterface 指示该类型是否是接口

IsPublic 指示该类型是否是公有的

IsSealed 指示该类型是否是密封类

IsValueType 指示该类型是否是值类型

Type类的方法:

GetConstructor(), GetConstructors():返回ConstructorInfo类型,用于取得该类的构造函数的信息

GetEvent(), GetEvents():返回EventInfo类型,用于取得该类的事件的信息

GetField(), GetFields():返回FieldInfo类型,用于取得该类的字段(成员变量)的信息

GetInterface(), GetInterfaces():返回InterfaceInfo类型,用于取得该类实现的接口的信息

GetMember(), GetMembers():返回MemberInfo类型,用于取得该类的所有成员的信息

GetMethod(), GetMethods():返回MethodInfo类型,用于取得该类的方法的信息

GetProperty(), GetProperties():返回PropertyInfo类型,用于取得该类的属性的信息

可以调用这些成员,其方式是调用Type的InvokeMember()方法,或者调用MethodInfo, PropertyInfo和其他类的Invoke()方法。*///Type attrs and method (some like isArray? isInterface? , get field, method, attrs...)//check a class is support some interfaceboolisSupportInterface2 = type3.GetInterfaces().Contains(typeof(IReadAble));boolisSupportInterface3 =typeof(IReadAble).IsAssignableFrom(type3);//focus the sequence 顺序, interface in front//check is a class is sub class of some classboolisSubClass2 = type3.IsSubclassOf(typeof(ParentClass));boolisSubClass3 =typeof(ParentClass).IsAssignableFrom(type3);//parentClass in front//2 way for new ClassDemoClass demo1 = (DemoClass)Activator.CreateInstance(type3);//use ActivatorConstructorInfo constructor = type3.GetConstructor(newType[0]);//use constructor no parameterDemoClass demo2 = (DemoClass)constructor.Invoke(newobject[0]);//no parameter//BindingFlags.DeclaredOnly ( no includ inherit )//BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static ( common use )//指定 BindingFlags.FlattenHierarchy 以便沿层次结构向上包括 public 和 protected 静态成员;不包括继承类中的 private 静态成员。( unknow )

 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
 
© 2005- 王朝網路 版權所有 導航