反射基础入门篇

1、简介

Reflection,中文翻译为反射。.Net的应用程序由以下几个部分组成:

a、程序集(assembly)

b、模块(moudle)

c、类型(class)

而通过反射技术可以让程序员在允许期间获取这几个组成部分的关键信息。

2、程序集和命名空间的关系

程序集是.Net应用程序的最小执行单位,通过vs编译工具编译出来的.dll文件就是程序集。

程序集和命名空间的对应关系如下:

a、一个程序集可以包含多个命名空间(命名空间名可以相同,如果命名空间相同,则类似parital关键字的效果)

b、一个命名空间也可以存在于多个程序集中

这里命名空间和类型的关系就不多做说明了

3、反射典型的应用

做过.Net开发的都知道三层模式,其中因为系统可能会存在更换数据库的情况,所以数据层会存在多种类型的情况,如SqlServer版的数据层或者是Oracle的数据层.所以业务层往往会依赖数据层的接口(不会直接和业务层耦合),并通过简单工厂(反射和配置文件)生成对应的数据库实例.

UserBll.cs

using IDal;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Bll
{
    public class UserBll
    {
        private IUserDal _userDal;
        public UserBll()
        {
            _userDal = DalFactory.DalMethodFactory.GetUserDal() as IUserDal;
        }

        public int AddUser()
        {
            return _userDal.AddUser();
        }
    }
}

IUserDal.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace IDal
{
    public interface IUserDal
    {
        int AddUser();
    }
}

DalMethodFactory.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace DalFactory
{
    public class DalMethodFactory
    {
        private readonly const string AssemblyName = "Dal";//可从配置文件中读取
        private readonly const string Namespace = "IDal";//可从配置文件中读取
     
     //通过反射创建指定的类型
        public static object CreateInstance(string type)
        {
            var assembly = Assembly.Load(AssemblyName);
            return assembly.CreateInstance(Namespace + type);
        }

        public static object GetUserDal()
        {
            string type =Namespace+".UserDal";
            return CreateInstance(type);
        }
    }
}

UserDal.cs

using IDal;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Dal
{
    public class UserDal:IUserDal
    {
        public int AddUser()
        { 
            return 1;
        }
    }
}

以上就是反射典型的应用.

3、反射常用的类型-System.Type类

(1)、Type是一个抽象类,当实例化了一个Type实例,实际上是实例化了一个Type的派生类。Type有与每种数据类型对应的派生类,它们一般不会添加新的方法或属性。获取任何给定类型的Type有三种方式:

a、通过typeof关键字

Type t=typeof(Test);

b、通过Object的实例方法GetType()

Type t=New Test().GetType();

c、通过Type的GetType()静态方法

Type t = Type.GetType("RnLn.Test");

(2)、Type的属性和方法介绍

Type是许多反射功能的入口,它实现许多方法和属性,这里不可能一一列举,只介绍一些常用的,主要介绍如何使用这个类。

注:Type的属性都是只读的,可以它们确定数据的类型,但是不能对它们进行修改.

属性:

a、Name   ---数据类型名

string str = "yes";
Type t = str.GetType();
Console.WriteLine(t.Name);

b、FullName   ---数据类型的完全限定名(不包括程序集)

string str = "yes";
Type t = str.GetType();
Console.WriteLine(t.FullName);

c、Namespace   ---数据类型的命名空间

d、Module   ---获取定义定义数据类型所在的dll程序集或者是.exe程序

Type t = new Test().GetType();
Console.WriteLine(t.Module);

e、BaseType   ---数据类型的"最近"基类型

Type t = new Test().GetType();
Console.WriteLine(t.BaseType);

f、UnderlyingSystemType   ---数据类型在.Net运行库中映射到的类型

Type t = new Test().GetType();
Console.WriteLine(t.UnderlyingSystemType);

g、IsXXX系列

IsAbstract(判断数据类型是否是抽象)、IsArray(是否为数组)、IsClass(是否为类)、IsEnum(是否为枚举)

方法:

System.Type的大多数方法用于获取对应数据类型的成员信息:构造函数、方法、属性和事件等。

a、GetMethods()   获取指定数据类型的所有的公共方法,有两个构造函数

参数:BindingFlags   ---类型搜索方法的标志。按照BindingFlags指定的规则去搜索指定类型的成员和方法.具体请参考MSDN

返回值:返回一个MethodInfo[]数组

    class Program
    {
        static void Main(string[] args)
        {
            
            Type t = new Test().GetType();
            MethodInfo[] methods=t.GetMethods();//获取Test类型的所有公共方法
            StringBuilder sb = new StringBuilder();
            for(int i=0;i<methods.Length;i++)
            {
                sb.Append("第" + (i + 1) + "个方法:");
                sb.Append(methods[i].Name);
                sb.AppendLine();
            }
            Console.WriteLine(sb.ToString());
        }
    }
    public class Test
    {
        public Test() { }
        public void Method1()
        {}
        public void Method2()
        {}
        public static void Method3()
        {}
    }

b、GetMthod()   ---按照参数,获取数据类型的指定的方法

参数:

Name   ---要获取的公共方法的名称

BindingFlags   ---类型搜索方法的标志。按照BindingFlags指定的规则去搜索指定类型的成员和方法.具体请参考MSDN

Binder   ---派生自定义的Binder类型,它可以几乎完全控制反射的工作方式(这里用几乎,是因为它受到了RuntimeType 实现时的一些限制)默认情况下使用的 System.DefaultBinder 类已经足够的使用了,因此不用太过于在意这个参数。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏cnblogs

async 和 await 之异步编程的学习

      async修改一个方法,表示其为异步方法。而await表示等待一个异步任务的执行。js方面,在es7中开始得以支持;而.net在c#5.0开始支持。...

2068
来自专栏魂祭心

原 c# params 工作原理。

3477
来自专栏菩提树下的杨过

Silverlight中的序列化

序列化简言之是这样一种能力:能够把复杂的对象(Object)变成某种格式的字符串(常见的格式有xml,string,二进制文件等),这样可以方便的在各种系统中传...

2025
来自专栏恰童鞋骚年

剑指Offer面试题:11.打印1到最大的n位数

  初看之下好像没有问题,但是其并没有考虑大数问题,有可能即使用整型(int)或长整型(long)都会溢出。

932
来自专栏犀利豆的技术空间

Redis 的基础数据结构(三)对象

前两篇文章介绍了 Redis 的基本数据结构动态字符串,链表,字典,跳跃表,压缩链表,整数集合,但是使用过 Redis 的同学会发现,平时根本没有使用过这些数...

1152
来自专栏码农分享

原型模式(Prototype)

原型模式的结构 原型模式包含以下3个角色: •Prototype(抽象原型类) •ConcretePrototype(具体原型类) •Client(客户...

1153
来自专栏大内老A

通过实例模拟ASP.NET MVC的Model绑定的机制:集合+字典

在本系列的前面两篇文章(《简单类型+复杂类型》、《数组》)我们通过创建的实例程序模拟了ASP.NET MVC默认使用的DefaultModelBinder对简单...

3017
来自专栏菩提树下的杨过

装箱与值类型虽然很容易理解,但是在实际使用中,并不总是能100%用对

public struct Point { private int m_x, m_y; public Poi...

2116
来自专栏菩提树下的杨过

C#执行XSL转换

xsl 可方便的将一种格式的xml,转换成另一种格式的xml,参考下面的代码: using System; using System.IO; using Sys...

2039
来自专栏用户3030674的专栏

Java中Json解析

首先准备一个JSON格式的字符串 * String JsonStr = "{object:{persons:" + "[{name:'呵呵',im...

3372

扫码关注云+社区

领取腾讯云代金券