C# 反射基础

1 在.NET中程序集是什么?

程序集(Assembly)以可执行文件(.exe)或动态链接库文件(.dll)的形式存在,是.NET应用程序构建的基本单元。程序集可用于部署、版本控制和设置安全权限等。

2.程序集的有哪些部分组成?

程序集(Assembly)是一个包含清单类型元数据CLR代码资源的文件。

清单

  • 程序集名称信息(包括简单名称FullName、版本号(AssemblyName.Version)、本地化信息(AssemblyName.CultureInfo)和公钥(AssemblyName.GetPublicKeyToken()));
  • 本程序集引用的其他程序集的列表(AssemblyName.GetReferencedAssemblies())
  • 组成程序集的文件列表
  • 一个表明某个类型在哪个程序集的地图

类型元数据

类型元数据(Type Metadata)是指描述类型的数据,它包含了类型的所有成员信息,例如类型的名称、基类、实现的接口、定义的方法、属性、事件、字段以及嵌套类型等。

类型元数据在编译时由编译器收集,并在运行时由.NET运行时使用,以便于进行类型检查、反射、动态调度等操作。

通过调用AssemblyName.GetTypes()可获取程序集所有的类型元数据

using System;
using System.Reflection;

class Program
{
    static void Main()
    {
        // 获取当前程序集
        Assembly assembly = Assembly.GetExecutingAssembly();

        // 获取程序集中的所有类型
        Type[] types = assembly.GetTypes();

        // 输出类型信息
        Console.WriteLine("程序集中的类型数量: " + types.Length);
        foreach (Type type in types)
        {
            Console.WriteLine("类型名称: " + type.Name);
            Console.WriteLine("类型全名: " + type.FullName);
            Console.WriteLine("类型所在的程序集: " + type.Assembly.FullName);
            Console.WriteLine();
        }
    }
}

CIL 代码
程序集不包含本机代码,而是包含公共中间语言(CIL)代码。程序的CIL直到被调用运行时才会被即时编译器(JIT)编译成本机代码。

资源
资源部分是可选的,可以包括图形和语言资源。

3. 什么是反射?

反射(reflection)是运行中的程序查看自身或者外部程序集的元数据的行为

4. 反射的作用是什么?

  • 类型检查:通过反射,可以在运行时获取类型信息,包括类型的名称、方法、属性、字段等
  • 动态实例化:使用反射可以动态地创建对象实例,即使编译器在编译时不知道这些类型
  • 调用方法:反射允许动态调用方法,这意味着可以在运行时决定调用哪个方法,而不是在编译时就确定下来。
  • 属性访问:可以通过反射来读取或设置对象的公共或私有属性值。
  • 事件处理:反射还可以用来绑定事件处理方法,这在某些动态事件处理场景中非常有用。

5. 什么是特性?

特性(Attributes)是一种特殊的类,它用于为程序中的其他程序结构(如类、方法、字段等)提供附加信息。

6. 为什么特性的使用往往需要反射?

因为,反射(reflection)是运行中的程序查看自身或者外部程序集的元数据的行为

且,特性(reflection)的生产过程如下:

  • 在源代码中将特性应用于目标程序结构;
  • 编译器在编译时从特性产生元数据,然后把元数据放到程序集中;

所以,可以通过反射获取特性的元数据,从而获取特性为目标程序结构附加的额外信息。

7. 为什么反射运行效率更低?

反射的运行效率通常低于直接代码执行,这是因为反射涉及到了动态解析类型信息和调用,而这些操作通常比静态编译的代码要慢。

具体来说,以下是导致反射效率较低的几个原因:

  • 动态解析:反射需要在运行时动态地解析类型信息,包括查找方法、属性和字段等。这个过程涉及到了字符串比较、字典查找等操作,相对于直接访问静态类型信息来说,这些动态操作会更加耗时;
  • 中间代码(IL)生成:反射调用方法时,需要动态生成中间代码(Intermediate Language,IL),这一过程比直接执行已经编译成中间代码的方法要慢.

8. 怎么在WPF中使用ValidationAttribute特性?

ValidationAttribute用于验证数据模型的属性值是否符合要求。

  1. 首先,创建一个自定义的ValidationAttribute类,继承自ValidationAttribute类,并重写IsValid方法;
using System.ComponentModel.DataAnnotations;

public class NotEmptyStringAttribute : ValidationAttribute
{
    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        if (value == null || string.IsNullOrEmpty(value.ToString()))
        {
            return new ValidationResult("不能为空");
        }

        return ValidationResult.Success;
    }
}
  1. 然后,在数据模型中使用这个自定义的验证器;
public class User
{
    [NotEmptyString]
    public string Name { get; set; }
}
  1. 最后,在XAML中使用数据绑定和验证
<Window x:Class="WpfApp1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfApp1"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <StackPanel>
            <TextBox Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}" />
            <Button Content="提交" Command="{Binding SubmitCommand}" />
        </StackPanel>
    </Grid>
</Window>
  • 11
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值