C#强化系列文章五:动态代码的使用(反射和动态生成类)

C#强化系列文章五:动态代码的使用(反射和动态生成类)

在软件开发尤其是框架和底层开发时,为了更灵活的控制代码,常常需要进行一些动态的操作。比如根据用户的输入等动态的调用类中的方法或者根据数据库表结构、用户要求动态的生成一些类,然后再动态的调用类中的方法。当然使用这些方式时会对性能有一点影响,具体使用过程中可以根据实际情况来定,不过一般的B/S开发中主要的瓶颈还是在数据库操作和网速方面,这点影响应该可以忽略的
下面我就从这两个方面来说说动态代码的使用:
一、反射的使用
可以使用反射动态地创建类型的实例,将类型绑定到现有对象,或从现有对象中获取类型。然后,可以调用类型的方法或访问其字段和属性。
需要使用的命名空间: System.Reflection
反射的作用很多,下面的例子主要是看一下怎么动态的调用类中的方法。

     class  ReflTest1
    
{
        
private   string  _prop1;

        
public   string  Prop1
        
{
            
get   return  _prop1; }
            
set   { _prop1  =  value; }
        }

    
        
public   void  Write1( string  strText)
        
{
            Console.WriteLine(
" 111111111: "   +  strText);
        }

        
public   void  Write2( string  strText)
        
{
            Console.WriteLine(
" 222222222: "   +  strText);
        }

        
public   void  MyWrite( string  strText)
        
{
            Console.WriteLine(
" 3333333333: "   +  strText);
        }

    }

这个例子中提供了三个方法和一个属性,下面的代码来动态的调用它们:
             string  strText  =   " abcd " ;

            BindingFlags flags 
=  (BindingFlags.NonPublic  |  BindingFlags.Public  |
                BindingFlags.Static 
|  BindingFlags.Instance  |  BindingFlags.DeclaredOnly);

            Type t 
=   typeof (ReflTest1);
            MethodInfo[] mi 
=  t.GetMethods(flags);
            Object obj 
=  Activator.CreateInstance(t);

            
foreach  (MethodInfo m  in  mi)
            
{
                
if  (m.Name.StartsWith( " Write " ))
                
{
                    m.Invoke(obj, 
new   object []  { strText } );
                }

            }


            MethodInfo mMy 
=  t.GetMethod( " MyWrite " );
            
if  (mMy  !=   null )
            
{
                mMy.Invoke(obj, 
new   object []  { strText } );
            }

BindingFlags用来设置要取得哪些类型的方法,然后我们就可以取得这些方法来动态的调用。(当然为了可以循环的调用方法,在方法的命名方面可以自己指定一个规则)

二、动态生成类
我们可以在程序运行过程中调用.NET中提供的编译类,动态的将一段string编译成一个类,然后再通过反射来调用它
需要使用的命名空间: System.CodeDom System.CodeDom.Compiler Microsoft.CSharp System.Reflection
动态创建、编译类的代码如下:
         public   static  Assembly NewAssembly()
        
{
            
// 创建编译器实例。   
            provider  =   new  CSharpCodeProvider();
            
// 设置编译参数。   
            paras  =   new  CompilerParameters();
            paras.GenerateExecutable 
=   false ;
            paras.GenerateInMemory 
=   true ;

            
// 创建动态代码。   
            StringBuilder classSource  =   new  StringBuilder();
            classSource.Append(
" public   class   DynamicClass /n " );
            classSource.Append(
" {/n " );

            
// 创建属性。   
            classSource.Append(propertyString( " aaa " ));
            classSource.Append(propertyString(
" bbb " ));
            classSource.Append(propertyString(
" ccc " ));

            classSource.Append(
" } " );

            System.Diagnostics.Debug.WriteLine(classSource.ToString());

            
// 编译代码。   
            CompilerResults result  =  provider.CompileAssemblyFromSource(paras, classSource.ToString());

            
// 获取编译后的程序集。   
            Assembly assembly  =  result.CompiledAssembly;

            
return  assembly;
        }


        
private   static   string  propertyString( string  propertyName)
        
{
            StringBuilder sbProperty 
=   new  StringBuilder();
            sbProperty.Append(
"  private   int   _ "   +  propertyName  +   "    =   0;/n " );
            sbProperty.Append(
"  public   int    "   +   ""   +  propertyName  +   " /n " );
            sbProperty.Append(
"  {/n " );
            sbProperty.Append(
"  get{   return   _ "   +  propertyName  +   " ;}   /n " );
            sbProperty.Append(
"  set{   _ "   +  propertyName  +   "    =   value;   }/n " );
            sbProperty.Append(
"  } " );
            
return  sbProperty.ToString();
        }
propertyString方法就是用来拼写字符串的
整个代码比较简单,主要步骤就是:1、拼写类的字符串  2、调用CSharpCodeProvider类进行编译得到程序集(assembly)

接下来就可以利用之前反射的方法来动态调用这个类中的属性了:
            Assembly assembly  =  NewAssembly();

            
object  Class1  =  assembly.CreateInstance( " DynamicClass " );
            ReflectionSetProperty(Class1, 
" aaa " 10 );
            ReflectionGetProperty(Class1, 
" aaa " );

            
object  Class2  =  assembly.CreateInstance( " DynamicClass " );
            ReflectionSetProperty(Class1, 
" bbb " 20 );
            ReflectionGetProperty(Class1, 
" bbb " );
DynamicClass是我动态类的类名,aaa和bbb是其中的属性
ReflectionSetProperty和ReflectionGetProperty代码如下:

         private   static   void  ReflectionSetProperty( object  objClass,  string  propertyName,  int  value)
        
{
            PropertyInfo[] infos 
=  objClass.GetType().GetProperties();
            
foreach  (PropertyInfo info  in  infos)
            
{
                
if  (info.Name  ==  propertyName  &&  info.CanWrite)
                
{
                    info.SetValue(objClass, value, 
null );
                }

            }

        }


         private   static   void  ReflectionGetProperty( object  objClass,  string  propertyName)
        
{
            PropertyInfo[] infos 
=  objClass.GetType().GetProperties();
            
foreach  (PropertyInfo info  in  infos)
            
{
                
if  (info.Name  ==  propertyName  &&  info.CanRead)
                
{
                    System.Console.WriteLine(info.GetValue(objClass, 
null ));
                }

            }

        }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值