c#关于反射与特性《一》---动态调用成员

  反射(reflection),按照定义,即为对程序集中的元数据进行检查的过程。而特性,按本人的理解,就是在程序集中插入自定义的元数据标记,为类或类成员(属性,方法,字段等)打上特定的标记,方便查找和调用。在.netFramework框架下,System.Reflection 及提供了充足的反射类型,,(MethodInfo, PropertyInfo, FieldInfo,等)均是在检查元数据过程中非常实用的类。对于反射有个不容忽视的强大特性,那就是在CAS(code-access-security)的前提下,它可以绕过访问等级制度(见以下示例),可以直接调用并对私有成员进行赋值,当然对于代码安全而言也是个不容忽视的漏洞隐患。 另外也因为有了反射和特性,因此出现了新型的编程模型,相对于OOP(面向对象),出现了AOP(面向方面编程,Aspect-oriented programing)足可见其强大。

以下为测试反射和特性的小例子,按照特性来查找类成员,并调用和赋值的例子,其中包括对私有属性和私有方法的访问。

访问私有成员时需要注意BindingFlags.NonPublic 以及为实例还是静态成员的BindingFlags.Instance;

文件1:

using System.IO;
using System;
using TestAttributes;
using System.Reflection;
class Program
{
    static void Main()
    {
        var type=typeof(TestClassA);
      
        //invoke the methods in TestClassA with ExportAttribute;
          ExportAttribute.InvokeMethod("TestMethod1",type,null);
          var parameters=new string[]{"anyname"};
          ExportAttribute.InvokeMethod("Print",type,parameters);
          
          //set the private property in TestClassA with value;
          var class1=new TestClassA();
         SetPropertyValue(class1,"level","LevelClass1");
         class1.Print("anynameclass1");
 
    }
    
    //Set property Value;
    public static bool SetPropertyValue(object target,string propertyName,object propertyValue)
    {
        var type=target.GetType();
        var property=type.GetProperty(propertyName,BindingFlags.NonPublic|BindingFlags.Instance|BindingFlags.Public);
        if(property!=null)
        {
        var attributes=property.GetCustomAttributes(false);
        foreach(var attribute in attributes)
        {
            if(attribute is ExportAttribute)
            {
                 property.SetValue(target,propertyValue,null);
                 return true;
            }
        }
        }
        return false;
    }
}

 

文件2:

using System.Reflection;
using System;
using System.IO;
namespace TestAttributes
{
    [AttributeUsage(AttributeTargets.Method|AttributeTargets.Property)]
    public class ExportAttribute: Attribute
    {
        public string catalogs {get;set;}
        
        //the classtype must have a default constructor; if the parameter of the method is null ,then the parameters must be null;
        public static bool InvokeMethod(string MethodName,Type classtype,object[] parameters)
        {
            if(MethodName==null||classtype==null)
            return false;
            var flag=false;
            var methodInfos=classtype.GetMethods(BindingFlags.Public|BindingFlags.NonPublic|BindingFlags.Instance);
            foreach(var info in methodInfos)
            {
                if(info.Name==MethodName&&IsHaveExportAttribute(info))
                {
                    flag=true;
                    var instance=Activator.CreateInstance(classtype);
                    info.Invoke(instance,parameters);
                }
            }
            return flag;
        }
        
        public static bool IsHaveExportAttribute(MethodInfo info)
        {
            if(info==null)
            {
                return false;
            }
            var attributes=info.GetCustomAttributes(false);
            foreach (var attribute in attributes)
            {
                if(attribute is ExportAttribute)
                {
                    return true;
                }
            }
            return false;
        }
    
    }
    
      public class TestClassA
    {
        private string name {get;set;}

        [Export]
        private string level {get;set;}
        
        public TestClassA()
        {
            name="DefaultName";
            level="DefaultLevel";
        }
        
        [Export]
        private void TestMethod1()
        {
             using (StreamReader reader = new StreamReader("input.txt"))
            {
                string line;
                while ((line = reader.ReadLine()) != null)
                {
                    Console.WriteLine(line);
                }
            }
            Console.ReadKey();
        }
        
        [Export]
        public void Print(string name)
        {
            Console.WriteLine(name);
            Console.WriteLine(level);
            Console.ReadKey();
        }
    }
}


 

输出:

Testing Reflection

**********************

anyname

DefaultLevel

anynameclass1

LevelClass1

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值