也谈.NET反射的封装

.NET反射提供了在运行时获取对象类型元数据的途径,使程序可以动态地调用对象的属性、方法。动态性带来的代价是反射调用不像基于静态类型的直接调用那样简洁,且缺乏类型检查机制,失去了IDE智能提示,容易出错;于是,不少朋友尝试对.NET反射进行封装。这个话题是仁者见仁,智者见智,这里我也谈谈自己对.NET反射封装的思路,请先看下面的示例代码:

static void Main(string[] args)
{
    Person liu 
= new Person("liu"26);

    Reflector reflector 
= new Reflector(liu);

    
//获取属性
    string name = reflector.Property<string>("Name");
    
int age = reflector.Property<int>("Age");
    Console.WriteLine(name 
+ " " + age);

    
//修改属性
    age = reflector.SetProperty<int>("Age"27);
    Console.WriteLine(name 
+ " " + age);

    
//获取过程
    Proc<string> sayHello = reflector.Proc<string>("SayHello");
    sayHello(
"Ling");

    
//获取函数
    Func<int> getAge = reflector.Func<int>("GetAge");
    age 
= getAge();
    Console.WriteLine(age);

    Console.ReadLine();
}

public class Person
{
    
private string name;
    
private int age;

    
public Person(string name, int age)
    {
        
this.name = name;
        
this.age = age;
    }

    
public string Name
    {
        
get { return name; }
    }

    
public int Age
    {
        
get { return age; }
        
set { age = value; }
    }

    
public void SayHello(string who)
    {
        Console.WriteLine(
"Say Hello to " + who);
    }

    
public int GetAge()
    {
        
return age;
    }
}


相信您已经从代码看出了封装的思路:利用泛型和泛型委托为动态的反射添加静态的类型约束。下面我们就来简单看一下Reflector实现的关键部分:

public delegate void Proc();
public delegate void Proc<T1>(T1 arg1);
public delegate void Proc<T1, T2>(T1 arg1, T2 args);
public delegate void Proc<T1, T2, T3>(T1 arg1, T2 args, T3 arg3);
public delegate void Proc<T1, T2, T3, T4>(T1 arg1, T2 args, T3 arg3, T4 arg4);
public delegate void Proc<T1, T2, T3, T4, T5>(T1 arg1, T2 args, T3 arg3, T4 arg4, T5 arg5);
public delegate R Func<R>();
public delegate R Func<T1, R>(T1 arg1);
public delegate R Func<T1, T2, R>(T1 arg1, T2 args);
public delegate R Func<T1, T2, T3, R>(T1 arg1, T2 args, T3 arg3);
public delegate R Func<T1, T2, T3, T4, R>(T1 arg1, T2 args, T3 arg3, T4 arg4);
public delegate R Func<T1, T2, T3, T4, T5, R>(T1 arg1, T2 args, T3 arg3, T4 arg4, T5 arg5);

public class Reflector
{
    
private object target;

    
public object Target
    {
        
get { return target; }
    }

    
public T Property<T>(string name)
    {
        PropertyInfo pi 
= target.GetType().GetProperty(name, typeof(T));

        
if (null != pi && pi.CanRead)
        {
            
object value = pi.GetValue(target, null);

            
if (null != value)
            {
                
return (T)value;
            }
        }

        
return default(T);
    }

    
public T SetProperty<T>(string name, T value)
    {
        PropertyInfo pi 
= target.GetType().GetProperty(name, typeof(T));

        
if (null != pi && pi.CanWrite)
        {
            pi.SetValue(target, value, 
null);
        }

        
return value;
    }

    
public Proc Proc(string name)
    {
        MethodInfo mi 
= target.GetType().GetMethod(name, Type.EmptyTypes);

        
if (null != mi)
        {
            
return Delegate.CreateDelegate(typeof(Proc), target, mi.Name, falseas Proc;
        }

        
return null;
    }

    
public Proc<T> Proc<T>(string name)
    {
        MethodInfo mi 
= target.GetType().GetMethod(name, new Type[] { typeof(T) });

        
if (null != mi)
        {
            
return Delegate.CreateDelegate(typeof(Proc<T>), target, mi.Name, falseas Proc<T>;
        }

        
return null;
    }

    
public Proc<T1, T2> Proc<T1, T2>(string name)
    {
        MethodInfo mi 
= target.GetType().GetMethod(name, new Type[] { typeof(T1), typeof(T2) });

        
if (null != mi)
        {
            
return Delegate.CreateDelegate(typeof(Proc<T1, T2>), target, mi.Name, falseas Proc<T1, T2>;
        }

        
return null;
    }

    
public Proc<T1, T2, T3> Proc<T1, T2, T3>(string name)
    {
        //...
    }

    
public Proc<T1, T2, T3, T4> Proc<T1, T2, T3, T4>(string name)
    {
        //...
    }

    
public Proc<T1, T2, T3, T4, T5> Proc<T1, T2, T3, T4, T5>(string name)
    {
        //...
    }

    
public Func<R> Func<R>(string name)
    {
        MethodInfo mi 
= target.GetType().GetMethod(name, Type.EmptyTypes);

        
if (null != mi)
        {
            
return Delegate.CreateDelegate(typeof(Func<R>), target, mi.Name, falseas Func<R>;
        }

        
return null;
    }

    
public Func<T1, R> Func<T1, R>(string name)
    {
        MethodInfo mi 
= target.GetType().GetMethod(name, new Type[] { typeof(T1) });

        
if (null != mi)
        {
            
return Delegate.CreateDelegate(typeof(Func<T1, R>), target, mi.Name, falseas Func<T1, R>;
        }

        
return null;
    }

    
public Func<T1, T2, R> Func<T1, T2, R>(string name)
    {
        //...
    }
}

 

 

封装的实现并不复杂,只是利用了泛型和泛型委托为调用者提供了强类型的属性和方法;除属性和方法的名称是动态的以为,其余的都可以加上类型约束。欢迎就此话题多多交流!

posted on 2009-04-30 13:11  Todd Wei  阅读(3231)  评论(8编辑  收藏  举报