c# 反射

本文详细介绍如何使用C#反射机制动态加载程序集,获取并调用类型、方法及属性,包括通过完全限定名称获取类型,创建对象,调用方法与属性,以及使用特定构造函数。同时,深入探讨了如何通过反射实例化带有参数的特性类,并进行有效性验证。

从程序集到方法和属性的调用

原文地址:https://www.cnblogs.com/siyi/p/5009032.html

//动态加载程序集
Assembly ass = Assembly.LoadFile(@"F:\Cheng_20140819\VS2012_WorkSpace\Assembly\Assembly\TestClassLibary\bin\Debug\TestClassLibary.dll");


//利用GetTypes获取所有类型 public  internal  都能拿到
Type[] ts = ass.GetTypes();
foreach (Type item in ts)
{
	Console.WriteLine(item.Name);
}


//只获取公开的类型
//获取导出的类型
Type[] publicTypes = ass.GetExportedTypes();
foreach (Type item in publicTypes)
{
	Console.WriteLine("--->>"+item.Name);
}



//获取特定的Type,类型需要完全限定名称 : 记得带上命名空间哟~
Type personType = ass.GetType("TestClassLibary.Person");




//根据特定的Type 来创建对象,无参数构造函数
object personObj = Activator.CreateInstance(personType);

//获取特定的方法
MethodInfo method = personType.GetMethod("Add");

//调用,参数1 代表获取的类型的对象 ,参数2  代表调用的方法的参数列表
object obj= method.Invoke(personObj, new object[] { 2, 3 });


//获取参数的类型
ParameterInfo[] args = methodInfo.GetParameters();
Args[0].ParameterType



//获取继承接口的类型
Type[] types = type.GetInterfaces()


//方法设置泛型
methodInfo.MakeGenericMethod(type);

//--------------------------------调用属性---------------------
Assembly ass = Assembly.LoadFile (@"F:\Cheng_20140819\VS2012_WorkSpace\Assembly\Assembly\TestClassLibary\bin\Debug\TestClassLibary.dll");

Type t = ass.GetType ("TestClassLibary.Person");

object obj = Activator.CreateInstance (t);

PropertyInfo pifo = t.GetProperty ("Name");

pifo.SetValue (obj, "cheng");

MethodInfo mifo = t.GetMethod ("WriteName");

mifo.Invoke (obj, null);

//--------------------------------利用特定的构造函数
Assembly ass = Assembly.LoadFile (@"F:\Cheng_20140819\VS2012_WorkSpace\20151129_Heima_Day11_Assembly\Assembly\TestClassLibary\bin\Debug\TestClassLibary.dll");

Type personType = ass.GetType ("TestClassLibary.Person");

//这里使用 ctor    GetConstructor()  其参数列表就 是指定的构造函数的列表 
ConstructorInfo ctor = personType.GetConstructor (new Type[] { typeof (string), typeof (int), typeof (string) });

object o = ctor.Invoke (new object[] { "ccc", 20, "CCC@sina.cn" });

Console.WriteLine (o.ToString ());
MethodInfo mInfo = personType.GetMethod ("WriteName");

mInfo.Invoke (o, null);

反射实例带参数的特性类

特性

public abstract class BaseValidationAttribute: Attribute
    {
        public BaseValidationAttribute(string errorMessage) {
            ErrorMessage = errorMessage;
        }

        public string ErrorMessage { get; set; }

        public abstract bool IsValid();
}



public class RoleAuthAttribute : BaseValidationAttribute
    {
        private List<string> _Role = new List<string>();

        public RoleAuthAttribute(object[] role) : base("授权错误") {
            foreach (var item in role) {
                _Role.Add(item.ToString());
            }
        }

        public RoleAuthAttribute(object[] role, string error) : base(error) {
            foreach (var item in role)
            {
                _Role.Add(item.ToString());
            }
        }

        public override bool IsValid()
        {
            IPrincipal principal = GenerateAndGetPrincipal.GetPrincipal();
            if (principal == null)
            {
                return false;
            }
            foreach (var item in _Role) {
                if (principal.IsInRole(item) == true)
                    return true;
            }

            return false;
        }
 }

验证

public static bool Validate(Type type,out string errorMessage)
        {
            errorMessage = null;

            foreach (var item in type.CustomAttributes)
            {
  				//获取构造函数信息
                ConstructorInfo service = item.Constructor;
                if (service.DeclaringType.IsSubclassOf(typeof(BaseValidationAttribute)))
                {
                    List<object> paramList = new List<object>();
					//获取构造函数实参信息
                    foreach(var parameterInfoItem in item.ConstructorArguments) {
                        List<object> list = new List<object>();
                        foreach (var parameterItem in (ReadOnlyCollection<CustomAttributeTypedArgument>) parameterInfoItem.Value) {
							//添加实参值
                            list.Add(parameterItem.Value);
                        }
                        paramList.Add(list.ToArray());
                    }
  					//调用构造方法生成特性实例
                    BaseValidationAttribute validationAttribute = service.Invoke(paramList.ToArray()) as BaseValidationAttribute;
				 	//调用特性的方法进行验证
                    bool isSuccess = validationAttribute.IsValid();
                    if (isSuccess == false)
                    {
                        errorMessage = validationAttribute.ErrorMessage;
                        return false;
                    }
                }
            }

            return true;
}

反射搜索标记 BindingFlags

例:查找当前类的方法公共方法,不包括父类

var type = typeof(ClassA);
var methods = type.GetMembers(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.DeclaredOnly);

BindingFlags.Instance和BindingFlags.Static二者必须有一项或者都有

BindingFlags枚举值:
BindingFlags.IgnoreCase:表示忽略 name 的大小写,不应考虑成员名的大小写
BindingFlags.DeclaredOnly:只应考虑在所提供类型的层次结构级别上声明的成员。不考虑继承成员。
BindingFlags.Instance:只搜索实例成员
BindingFlags.Static:只搜索静态成员
BindingFlags.Public:只搜索公共成员
BindingFlags.NonPublic:只搜索非公共成员
BindingFlags.FlattenHierarchy:应返回层次结构上的公共静态成员和受保护的静态成员。不返回继承类中的私有静态成员。静态成员包括字段、方法、事件和属性。不返回嵌套类型。
BindingFlags.InvokeMethod:表示调用方法,而不调用构造函数或类型初始值设定项。对 SetField 或 SetProperty 无效。
BindingFlags.CreateInstance:表示调用构造函数。忽略 name。对其他调用标志无效。
BindingFlags.GetField:表示获取字段值。
BindingFlags.SetField:表示设置字段值。
BindingFlags.GetProperty:表示获取属性。
BindingFlags.SetProperty:表示设置属性。

<think>好的,我需要回答用户关于C#反射的使用指南和示例的问题。首先,我得回忆反射的基本概念,反射C#中主要用于在运行时获取类型信息,动态创建对象,调用方法等。用户可能需要具体的步骤和代码示例,所以我得按照逻辑顺序组织内容。首先,应该介绍反射的核心类,比如Type、Assembly、Activator、MethodInfo等。然后分步骤讲解如何获取类型信息、动态创建实例、访问成员和调用方法。每个部分都需要示例代码,确保用户能理解如何实际操作。 接下来,用户可能关心反射的应用场景,比如插件系统、序列化、ORM框架等,这些可以作为高级应用部分。同时,需要注意提到反射的性能问题,虽然功能强大,但过度使用会影响性能,可以建议使用缓存或表达式树优化。 然后,生成相关问题。我需要考虑用户可能的后续问题,比如性能优化、替代方案、动态加载程序集等,确保问题覆盖常见的使用场景和潜在疑问。检查引用部分,用户提供的引用提到了反射获取构造函数信息创建对象,这和动态实例化部分相关,需要正确引用。同时,确保代码示例正确,使用正确的语法,比如typeof、GetType、Activator.CreateInstance等方法。最后,确保回答符合系统级指令:使用中文,数学公式正确,引用标识自然添加。特别是没有使用任何markdown格式,代码块用三个反引号包裹,并注明语言。结构清晰,分步骤讲解,帮助用户逐步掌握反射的使用。</think>### C# 反射使用指南及示例 #### 1. 反射核心类与基础用法 反射的核心类是`System.Type`,可通过以下方式获取类型信息: ```csharp // 通过类型名获取 Type type1 = typeof(string); // 通过实例获取 Type type2 = "test".GetType(); // 通过程序集获取 Type type3 = Assembly.GetExecutingAssembly().GetType("Namespace.ClassName"); ``` #### 2. 动态创建对象 使用`Activator`类创建实例: ```csharp Type type = typeof(MyClass); object instance = Activator.CreateInstance(type); // 带参数的构造函数 object paramInstance = Activator.CreateInstance(type, new object[] { "参数" }); ``` #### 3. 访问成员信息 获取成员变量和方法: ```csharp // 获取所有公共方法 MethodInfo[] methods = type.GetMethods(); // 获取私有字段 FieldInfo field = type.GetField("_privateField", BindingFlags.NonPublic | BindingFlags.Instance); // 获取属性 PropertyInfo property = type.GetProperty("Name"); ``` #### 4. 动态调用方法 ```csharp MethodInfo method = type.GetMethod("MyMethod"); object result = method.Invoke(instance, new object[] { 参数 }); // 调用私有方法示例 MethodInfo privateMethod = type.GetMethod("HiddenMethod", BindingFlags.NonPublic | BindingFlags.Instance); privateMethod.Invoke(instance, null); ``` #### 5. 典型应用场景 - **插件系统开发**:动态加载DLL并调用功能 - **序列化/反序列化**:自动处理未知类型 - **ORM框架**:动态映射数据库字段到对象属性 - **DI容器**:实现依赖注入 #### 6. 性能优化建议 - 对重复使用的反射操作进行缓存 - 使用`dynamic`类型或表达式树优化高频调用 - 优先使用泛型方法:`MethodInfo.MakeGenericMethod()` ```csharp // 表达式树优化示例 var param = Expression.Parameter(typeof(MyClass)); var lambda = Expression.Lambda<Action<MyClass>>( Expression.Call(param, methodInfo), param); var compiled = lambda.Compile(); compiled(obj); // 接近原生调用速度 ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值