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

来源:互联网 发布:等式约束优化 数值求解 编辑:程序博客网 时间:2024/06/06 13:02

  反射(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

 

 

原创粉丝点击