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));
                }

            }

        }

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
生成实体代码通常是为了避免手动编写大量重复的代码,提高开发效率和代码质量。C#可以使用反射和代码生成动态生成实体代码。 在使用反射生成实体代码时,可以通过反射获取实体的字段信息,然后使用代码生成的方式生成实体代码。以下是一个简单的示例: ```csharp using System; using System.Reflection; using System.CodeDom; using System.CodeDom.Compiler; using Microsoft.CSharp; namespace DynamicEntity { class Program { static void Main(string[] args) { // 创建 CodeCompileUnit 对象 CodeCompileUnit compileUnit = new CodeCompileUnit(); // 添加命名空间 CodeNamespace codeNamespace = new CodeNamespace("DynamicEntity"); compileUnit.Namespaces.Add(codeNamespace); // 添加引用 codeNamespace.Imports.Add(new CodeNamespaceImport("System")); // 创建 CodeTypeDeclaration classDeclaration = new CodeTypeDeclaration("Person"); classDeclaration.IsClass = true; classDeclaration.TypeAttributes = TypeAttributes.Public; // 添加字段 CodeMemberField field1 = new CodeMemberField(typeof(int), "_id"); field1.Attributes = MemberAttributes.Private; classDeclaration.Members.Add(field1); CodeMemberField field2 = new CodeMemberField(typeof(string), "_name"); field2.Attributes = MemberAttributes.Private; classDeclaration.Members.Add(field2); // 添加属性 CodeMemberProperty property1 = new CodeMemberProperty(); property1.Attributes = MemberAttributes.Public | MemberAttributes.Final; property1.Name = "Id"; property1.Type = new CodeTypeReference(typeof(int)); property1.GetStatements.Add(new CodeMethodReturnStatement(new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), "_id"))); property1.SetStatements.Add(new CodeAssignStatement(new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), "_id"), new CodePropertySetValueReferenceExpression())); classDeclaration.Members.Add(property1); CodeMemberProperty property2 = new CodeMemberProperty(); property2.Attributes = MemberAttributes.Public | MemberAttributes.Final; property2.Name = "Name"; property2.Type = new CodeTypeReference(typeof(string)); property2.GetStatements.Add(new CodeMethodReturnStatement(new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), "_name"))); property2.SetStatements.Add(new CodeAssignStatement(new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), "_name"), new CodePropertySetValueReferenceExpression())); classDeclaration.Members.Add(property2); // 添加到命名空间 codeNamespace.Types.Add(classDeclaration); // 生成代码 CSharpCodeProvider provider = new CSharpCodeProvider(); CodeGeneratorOptions options = new CodeGeneratorOptions(); options.BracingStyle = "C"; string fileName = "Person.cs"; using (System.IO.StreamWriter sourceWriter = new System.IO.StreamWriter(fileName)) { provider.GenerateCodeFromCompileUnit(compileUnit, sourceWriter, options); } Console.WriteLine("代码已生成到文件:{0}", fileName); Console.ReadKey(); } } } ``` 运行上述代码后,会生成一个名为“Person.cs”的文件,内容如下: ```csharp namespace DynamicEntity { using System; public class Person { private int _id; private string _name; public virtual int Id { get { return this._id; } set { this._id = value; } } public virtual string Name { get { return this._name; } set { this._name = value; } } } } ``` 这是一个简单的实体代码,包含了两个字段和对应的属性。可以根据实际需求来动态生成更加复杂的实体代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值