2018-8-10-win10-uwp-反射
| title | author | date | CreateTime | categories |
|---|---|---|---|---|
|
win10 uwp 反射
|
lindexi
|
2018-08-10 19:17:19 +0800
|
2018-2-13 17:23:3 +0800
|
UWP WPF 反射
|
本文在h神的指导下完成。
反射是强大的好用的,我们可以添加新功能不修改之前的代码,通过使用反射得到。
本文下面和大家说如何做一个和WPF一样的反射功能,如何才能获的 UWP 程序集所有类。
先来说下反射。
.Net 最小单位是装配件,什么是装配件?其实就是 dll 或 exe 。.Net 程序包括 程序集 ,模块 , 类型 这几个。反射可以在程序运行得到这几个组成部分的相关信息。
反射可以获得Assembly,他可以获得正在运行的装配件信息,也可以动态的加载装配件,以及在装配件中查找类型信息,并创建该类型的实例。可以获得Type,他可以获得对象的类型信息,包括属性方法,可以调用属性方法。可以获得MethodInfo,他可以得到类方法的参数、返回值,可以调用方法。和MethodInfo差不多的,还有很多,都在System.Reflection可以看到。
反射是做什么?反射其实应用在对于类型差不多,但是需要对修改时不需要修改多处的代码使用。
可以使用反射动态地创建类型的实例,将类型绑定到现有对象,或从现有对象中获取类型
应用程序需要在运行时从某个特定的程序集中载入一个特定的类型,以便实现某个任务时可以用到反射
反射主要应用与类库,这些类库需要知道一个类型的定义,以便提供更多的功能。
在我写的MVVM,就使用反射获得ViewModel,这样添加ViewModel 不需要修改写的代码。
反射可以添加类型不需要修改代码,这是很好的,但是反射性能比较差,在需要使用的时候才使用反射,不要每次都使用。
编译可以知道类型写错,反射不知道,可以得到错误的,一般使用反射需要小心,如果使用一些工具修改,那么反射得到的容易错误,好在C# 6有 name of 可以获得一个属性或方法的名称,这样使用他进行反射,得到的值才不容易出错。
反射可以获得安全类型的类,如internal或其他不是public的访问的类或类的字段,都可以获得。
uwp 程序集所有类
在使用反射之前需要打开Default.rd.xml添加下面代码,就可以反射这个项目代码
<Directives xmlns="http://schemas.microsoft.com/netfx/2013/01/metadata">
<Application>
<!-- Name="*Application*" 的程序集元素将应用到应用程序包中的所有程序集。星号不是通配符。-->
<Assembly Name="*Application*" Dynamic="Required All" />
</Application>
</Directives>
参见:设置 .NET Native 运行时指令以支持反射(尤其适用于 UWP) - walterlv
我们可以使用下面代码获得程序集所有的类
Application.Current.GetType().GetTypeInfo().Assembly
foreach (var temp in applacationAssembly.DefinedTypes)
{ }
那么我们如何获得属于ViewModel的类,如果我们没有继承base,那我们有简单方法。
public class ViewModelAssembly:Attribute
{ }
[ViewModelAssembly]
public class DstidModel : ViewModelBase
我们可以通过Attribute,查看是否有,如果有,就是ViewModel
foreach (var temp in applacationAssembly.DefinedTypes)
{
if (temp.CustomAttributes.Any(t => t.AttributeType == typeof(ViewModelAssembly)))
{ }
}
当然我们还修改下,因为我们不需要写那么多
var applacationAssembly = Application.Current.GetType().GetTypeInfo().Assembly;
foreach (var temp in applacationAssembly.DefinedTypes
.Where(temp=>temp.CustomAttributes.Any(t => t.AttributeType == typeof(ViewModelAssembly))))
{ }
那么我们可以使用type得到ViewModel,参见http://lindexi.oschina.io/lindexi/post/win10-uwp-%E4%BB%8EType%E4%BD%BF%E7%94%A8%E6%9E%84%E9%80%A0/
判断类型继承
经常需要判断 UWP 的类是否继承接口,如果需要判断继承接口,可以使用下面代码
- 判断类型是否接口
type.GetTypeInfo().IsInterface
就可以判断是否接口
接口的判断继承和类不同,接口判断使用下面的方式。这里 type 是一个类型,而 a 就是一个实例。
type.IsAssignableFrom(a.GetType().GetTypeInfo());
上面的代码可以写为
type.IsInstanceOfType(a)
如果不是接口,可以使用下面代码
a.GetType().GetTypeInfo().IsSubclassOf(type);
获得特性
例如已经拿到 TypeInfo ,他的扩展方法可以拿到特定的特性,一般获得特性就是这个方法,请看代码。
var attribute = type.GetCustomAttribute<LindexiAttribute>();
上面代码用于获得在对应类型的LindexiAttribute特性,于是就可以获得特性的实例,直接使用特性的属性就可以。
设置 .NET Native 运行时指令以支持反射(尤其适用于 UWP) - walterlv
解决 Relase 上无法使用反射的问题
WPF 反射获得所有类
Assembly assembly = Assembly.GetExecutingAssembly();
foreach (var temp in assembly.GetTypes())
{ }
获得类型
- typeof
Type type = typeof(类型);
- System.Object.GetType
所有的类存在的方法,通过一个实例,可以获得实例的
类型 t = new 类型();
Type type=t.GetType();
- System.Type.GetType
Type type=Type.GetType("cvte.类型",false,true);
注意参数0是类名,参数1表示若找不到对应类时是否抛出异常,参数1表示类名是否区分大小写
创建对象
创建对象的方法很多
Assembly assembly = Assembly.Load("Assembly");
Type type = assembly.GetType("Example");
object obj =Activator.CreateInstance(type);
可以传入参数,参数可以传入多个
object obj = Activator.CreateInstance(type,参数);
另一个方法
object obj = type.Assembly.CreateInstance(type.FullName);
反射私有构造方法
上面说的没有告诉大家如何在 C# 反射私有构造方法创建,下面来告诉大家如何写
首先需要获得构造函数,如果构造函数不是 public 那么就需要使用下面代码获得
获得方法
获得类型方法
MethodInfo[] listMethodInfo = type.GetMethods();
使用方法
object obj =Activator.CreateInstance(type);
MethodInfo methodInfo = type.GetMethod("方法");
methodInfo.Invoke(obj,null); //参数1类型为object[],代表方法的对应参数,输入值为null代表没有参数
使用存在 ref 和 out 的函数
如果反射存在 out 参数的函数,那么需要使用 parameters 方法来调用。
如果有一个方法是 foo(out string str) 那么可以使用下面的方法来调用
var method = type.GetMethod("foo")
var parameters = new object[]{""};
method.Invoke(null, parameters);//null 需要修改为需要的类
string str = parameters[0];//这个方式可以拿到值
如果是 ref 也是相同的方法。
获得属性
object obj =Activator.CreateInstance(type);
PropertyInfo propertyInfo = obj.GetProperty("Name"); //获取Name属性对象
var name = propertyInfo.GetValue(obj,null); //获取Name属性的值
propertyInfo.SetValue(obj,"cvte",null); //设置Name属性
静态字段
如果需要使用反射获得静态属性,可以使用下面的代码
type.GetField("foo",
BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static).GetValue(null) //输出 lindexi
foo 的定义请看下面
static class Foo
{
private static readonly string foo="lindexi";
}
获得Attribute
object[] typeAttributes = type.GetCustomAttributes(false);
判断一个类是另一个的子类
class A
{ } class A1:A
{ } A1 a=new A1();
a.GetType().IsSubclassOf(typeof(A)) 如果返回true,那么a就是继承 A
注意,虽然可以使用BaseType判断,但是如果继承多了,那么判断是否存在A,是不对的。
虽然说了很多,但很多都是大神讲的,于是
推荐大神讲的反射:http://www.cnblogs.com/wangshenhe/p/3256657.html
https://www.codeproject.com/Articles/55710/Reflection-in-NET
反射判断类继承接口
判断一个类继承接口的方法不可以使用 IsSubclassOf 判断
假如有下面的代码
interface IA
{ } class A : IA
{ }
这个代码会返回false a.GetType().IsSubclassOf(typeof(IA));
那么在C#如何判断一个类继承了接口,和一个类实现了接口?
使用方法是用 接口的IsAssignableFrom进行判断
A a = new A();
Console.WriteLine(typeof(IA).IsAssignableFrom(a.GetType()));
这时返回的是 true。
实际上 IsAssignableFrom 不仅可以用在接口,还可以用在类型,无论是什么的判断,这个方法的意思是,传入的类型是否继承于这个类型。所以只要判断继承,就可以使用这个方法。
请看下面例子,存在类型Room、Kitchen、Bedroom、Guestroom、MasterBedroom 继承关系如下
class Room
{
} class Kitchen : Room
{
} class Bedroom : Room
{
} class Guestroom : Bedroom
{
} class MasterBedroom : Bedroom
{
}
这时使用下面的代码判断继承
Room room1 = new Room();
Kitchen kitchen1 = new Kitchen();
Bedroom bedroom1 = new Bedroom();
Guestroom guestroom1 = new Guestroom();
MasterBedroom masterbedroom1 = new MasterBedroom(); Type room1Type = room1.GetType();
Type kitchen1Type = kitchen1.GetType();
Type bedroom1Type = bedroom1.GetType();
Type guestroom1Type = guestroom1.GetType();
Type masterbedroom1Type = masterbedroom1.GetType(); Console.WriteLine("room assignable from kitchen: {0}", room1Type.IsAssignableFrom(kitchen1Type));
Console.WriteLine("bedroom assignable from guestroom: {0}", bedroom1Type.IsAssignableFrom(guestroom1Type));
Console.WriteLine("kitchen assignable from masterbedroom: {0}", kitchen1Type.IsAssignableFrom(masterbedroom1Type));
可以看到有下面的输出
// room assignable from kitchen: True
// bedroom assignable from guestroom: True
// kitchen assignable from masterbedroom: False
只要存在继承,那么就是返回true,如果不存在,那么返回false
如果自己和自己比较?如Console.WriteLine("room assignable from room: {0}", typeof(Room).IsAssignableFrom(typeof(Room))); 会返回true
如果类型 A 继承 B ,无论B是接口还是类,B.IsAssignableFrom(A) 返回 true 。如果 A 和 B 类型相同,那么同样返回 true
但是 IsAssignableFrom 使用的是类型,如果有一个类实现,可以尝试下面代码
typeof(IA).IsInstanceOfType(a)
这个方法也可以获得类是否继承接口。
性能
但是不管怎么说,反射都是伤性能
2018-8-10-win10-uwp-反射的更多相关文章
- win10 uwp 反射
本文在h神的指导下完成. 反射是强大的好用的,我们可以添加新功能不修改之前的代码,通过使用反射得到. 本文下面和大家说如何做一个和WPF一样的反射功能,如何才能获的 UWP 程序集所有类. 先来说下反 ...
- win10 uwp 使用 Microsoft.Graph 发送邮件
在 2018 年 10 月 13 号参加了 张队长 的 Office 365 训练营 学习如何开发 Office 365 插件和 OAuth 2.0 开发,于是我就使用 UWP 尝试使用 Micros ...
- Win10 UWP开发实现Bing翻译
微软在WP上的发展从原来的Win7到Win8,Win8.1,到现在的Win10 UWP,什么是UWP,UWP即Windows 10 中的Universal Windows Platform简称.即Wi ...
- Win10/UWP开发—使用Cortana语音与App后台Service交互
上篇文章中我们介绍了使用Cortana调用前台App,不熟悉的移步到:Win10/UWP开发—使用Cortana语音指令与App的前台交互,这篇我们讲讲如何使用Cortana调用App的后台任务,相比 ...
- Win10 UWP应用发布流程
简介 Win10 UWP应用作为和Win8.1 UAP应用不同的一种新应用形式,其上传至Windows应用商店的流程也有了一些改变. 这篇博文记录了我们发布一款Win10 UWP应用的基本流程,希望为 ...
- win10 uwp 列表模板选择器
本文主要讲ListView等列表可以根据内容不同,使用不同模板的列表模板选择器,DataTemplateSelector. 如果在 UWP 需要定义某些列的显示和其他列不同,或者某些行的显示和其他行不 ...
- win10 uwp MVVM 轻量框架
如果在开发过程,遇到多个页面之间,需要传输信息,那么可能遇到设计的问题.如果因为一个页面内包含多个子页面和多个子页面之间的通信问题找不到一个好的解决方法,那么请看本文.如果因为ViewModel代码越 ...
- win10 uwp 获得元素绝对坐标
有时候需要获得一个元素,相对窗口的坐标,在修改他的位置可以使用. 那么 UWP 如何获得元素坐标? 我提供了一个方法,可以获得元素的坐标. 首先需要获得元素,如果没有获得元素,那么如何得到他的坐标? ...
- win10 uwp 毛玻璃
毛玻璃在UWP很简单,不会和WPF那样伤性能. 本文告诉大家,如何在 UWP 使用 win2d 做毛玻璃. 毛玻璃可以使用 win2D 方法,也可以使用 Compositor . 使用 win2d 得 ...
- win10 uwp 读取保存WriteableBitmap 、BitmapImage
我们在UWP,经常使用的图片,数据结构就是 BitmapImage 和 WriteableBitmap.关于 BitmapImage 和 WriteableBitmap 区别,我就不在这里说.主要说的 ...
随机推荐
- 使用python解析C代码
我有一个巨大的C文件(~100k行),我需要能够解析.主要是我需要能够从其定义中获取有关每个结构的各个字段的详细信息(如结构中每个字段的字段名称和类型).是否有一个好的(开源,我可以在我的代码中使用) ...
- Neo4J空间数据存储
1.Neo4j Spatial 简介 1.1Neo4j Spatial概念 Neo4j Spatial项目是图数据库Neo4j的一个插件,它通过将空间数据映射到图模型(graph model),它将对 ...
- JSP界面引用百度地图获取坐标
需求: 需要在JSP界面上引用百度地图,文本框中输入地址之后,自动拿到在百度地图上的经纬度 解决步骤: 1.引入百度地图api: head中进行引用<script type="text ...
- 使用TPL取回Task中的运行结果的三种方式
概念:TPL( Task Parallel Library) 任务并行库 使用Task类执行多线程操作要比直接使用自己手工创建Thread效率高很多. 默认情况下,TPL使用线程池中的线程执行Task ...
- 安装express 出现 错误
w 在网上找了很多都解决不了问题,直到换了文件新建路径就可以了 成功: 学习就是不断发现问题解决问题的过程
- h5开发与pc开发的差异性
1. viewport 将layout viewport 设置成ideal viewport . width=device-width,也可以设置 initial-scale=1,最好两者都有. wi ...
- 初试avalon
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- Java 基础 - 单行初始化数组 Initialize array in one line
Code: public class ClassName { private char[] value = new char[]{'a','b'}; private char[] value2 = { ...
- Vue学习笔记【3】——Vue指令之v-bind的三种用法
直接使用指令v-bind 使用简化指令: 在绑定的时候,拼接绑定内容::title="btnTitle + ', 这是追加的内容'" <!DOCTYPE html> & ...
- Comet Contest#11 F arewell(DAG计数+FWT子集卷积)
传送门. 题解: 4月YY集训时做过DAG计数,和这个基本上是一样的,但是当时好像直接暴力子集卷积,不然我省选时不至于不会,这个就多了个边不选的概率和子集卷积. DAG计数是个套路来的,利用的是DAG ...