Emit 和 CodeDom 都是用来动态创建类型,并利用反射执行的东东~~~~ 这两个都是 .NET Framework 中比较有深度的内容。
有关 CodeDom,雨痕已经写过好几篇了,此处不再详述。CodeDom 利用 C#/VB.NET 等编译引擎进行动态编译,而 Emit 则直接使用 IL,从编程方便的角度来说 CodeDom 更方便一点。当然 CodeDom 要花费一定的编译时间,而一旦载入则和 Emit 或静态编译程序集没有什么区别。Emit 被很多 AOP/ORM 组件所使用,除了 ILGenerator 外,和 CodeDom 的编程习惯很相似。接下来雨痕会写几篇 Emit 的使用文章。
好了,从经典的 "Hello, World!" 开始。我们本次的目标是用 Emit 重写下面的类型,并完成动态调用。
![ContractedBlock.gif](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![ExpandedBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
using
System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.CodeDom;
using System.Reflection;
using System.Reflection.Emit;
using Microsoft.CSharp;
using System.CodeDom.Compiler;
using System.Globalization;
namespace ConsoleApplication5
{
/// <summary>
/// Emit 和 CodeDom 都是用来动态创建类型,并利用反射执行的东东~~~~
/// </summary>
class Program
{
static void Main( string [] args)
{
/*
//一,Emit 则直接使用 IL
//1. 定义动态程序集
AssemblyName assemblyName = new AssemblyName("Nettip.Assembly");
AssemblyBuilder assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
//2. 定义动态模块
ModuleBuilder module = assembly.DefineDynamicModule("Nettip.QueryOrderConditon.Module");
//3. 定义类型
TypeBuilder type = module.DefineType("QueryOrderCondition", TypeAttributes.Class, typeof(object));
//4. 定义方法
MethodBuilder method = type.DefineMethod("Test", MethodAttributes.Public, CallingConventions.HasThis, null, null);
//5. 方法代码
ILGenerator il = method.GetILGenerator();
il.Emit(OpCodes.Nop);
il.Emit(OpCodes.Ldstr, "Hello, World!");
il.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }));
il.Emit(OpCodes.Nop);
il.Emit(OpCodes.Ret);
//6. 执行
Type class1 = type.CreateType();
object o = Activator.CreateInstance(class1);
o.GetType().GetMethod("Test").Invoke(o, null);
*/
// 二,CodeDom 利用 C#/VB.NET 等编译引擎进行动态编译
#region
// 1. 使用CodeDom创建源码
// CodeCompileUnit cu = new CodeCompileUnit();
// CodeNamespace Samples = new CodeNamespace("Samples");
// cu.Namespaces.Add(Samples);
// Samples.Imports.Add(new CodeNamespaceImport("System"));
// CodeTypeDeclaration Class1 = new CodeTypeDeclaration("Class1");
// Samples.Types.Add(Class1);
// CodeEntryPointMethod Start = new CodeEntryPointMethod();
// CodeMethodInvokeExpression cs1 = new CodeMethodInvokeExpression(
// new CodeTypeReferenceExpression("System.Console"), "WriteLine",
// new CodePrimitiveExpression("Hello World!") );
// Start.Statements.Add(new CodeExpressionStatement(cs1));
// Class1.Members.Add(Start);
string code = @"
using System;
namespace Nettip
{
public class QueryOrderCondition
private string name;
public QueryOrderCondition(string name)
{
this.name = name;
}
public void Test()
{
Console.WriteLine(""{0} - {1}"", name, DateTime.Now);
}
}
}
" ;
#endregion
// 1. 创建编译器对象
CodeDomProvider provider = CodeDomProvider.CreateProvider( " CSharp " );
// 2. 设置编译参数
CompilerParameters cp = new CompilerParameters();
cp.ReferencedAssemblies.Add( " System.dll " );
cp.GenerateInMemory = false ;
cp.OutputAssembly = " Nettip.QueryOrderCondition.dll " ;
// 3. 开始编译
CompilerResults results = provider.CompileAssemblyFromSource(cp, code);
// 3.1 显示编译信息
if (results.Errors.Count == 0 )
Console.WriteLine( " \ " { 0 }\ " compiled ok! " , results.CompiledAssembly.Location);
else
{
Console.WriteLine( " Complie Error: " );
foreach (CompilerError error in results.Errors)
Console.WriteLine( " {0} " , error);
}
// 4.执行
Type t = results.CompiledAssembly.GetType( " Nettip.QueryOrderCondition " );
object o = results.CompiledAssembly.CreateInstance( " Nettip.QueryOrderCondition " , false , BindingFlags.Default,
null , new object [] { " Tom " }, CultureInfo.CurrentCulture, null );
t.InvokeMember( " Test " , BindingFlags.Instance | BindingFlags.Public | BindingFlags.InvokeMethod,
null , o, null );
}
}
}
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.CodeDom;
using System.Reflection;
using System.Reflection.Emit;
using Microsoft.CSharp;
using System.CodeDom.Compiler;
using System.Globalization;
namespace ConsoleApplication5
{
/// <summary>
/// Emit 和 CodeDom 都是用来动态创建类型,并利用反射执行的东东~~~~
/// </summary>
class Program
{
static void Main( string [] args)
{
/*
//一,Emit 则直接使用 IL
//1. 定义动态程序集
AssemblyName assemblyName = new AssemblyName("Nettip.Assembly");
AssemblyBuilder assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
//2. 定义动态模块
ModuleBuilder module = assembly.DefineDynamicModule("Nettip.QueryOrderConditon.Module");
//3. 定义类型
TypeBuilder type = module.DefineType("QueryOrderCondition", TypeAttributes.Class, typeof(object));
//4. 定义方法
MethodBuilder method = type.DefineMethod("Test", MethodAttributes.Public, CallingConventions.HasThis, null, null);
//5. 方法代码
ILGenerator il = method.GetILGenerator();
il.Emit(OpCodes.Nop);
il.Emit(OpCodes.Ldstr, "Hello, World!");
il.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }));
il.Emit(OpCodes.Nop);
il.Emit(OpCodes.Ret);
//6. 执行
Type class1 = type.CreateType();
object o = Activator.CreateInstance(class1);
o.GetType().GetMethod("Test").Invoke(o, null);
*/
// 二,CodeDom 利用 C#/VB.NET 等编译引擎进行动态编译
#region
// 1. 使用CodeDom创建源码
// CodeCompileUnit cu = new CodeCompileUnit();
// CodeNamespace Samples = new CodeNamespace("Samples");
// cu.Namespaces.Add(Samples);
// Samples.Imports.Add(new CodeNamespaceImport("System"));
// CodeTypeDeclaration Class1 = new CodeTypeDeclaration("Class1");
// Samples.Types.Add(Class1);
// CodeEntryPointMethod Start = new CodeEntryPointMethod();
// CodeMethodInvokeExpression cs1 = new CodeMethodInvokeExpression(
// new CodeTypeReferenceExpression("System.Console"), "WriteLine",
// new CodePrimitiveExpression("Hello World!") );
// Start.Statements.Add(new CodeExpressionStatement(cs1));
// Class1.Members.Add(Start);
string code = @"
using System;
namespace Nettip
{
public class QueryOrderCondition
private string name;
public QueryOrderCondition(string name)
{
this.name = name;
}
public void Test()
{
Console.WriteLine(""{0} - {1}"", name, DateTime.Now);
}
}
}
" ;
#endregion
// 1. 创建编译器对象
CodeDomProvider provider = CodeDomProvider.CreateProvider( " CSharp " );
// 2. 设置编译参数
CompilerParameters cp = new CompilerParameters();
cp.ReferencedAssemblies.Add( " System.dll " );
cp.GenerateInMemory = false ;
cp.OutputAssembly = " Nettip.QueryOrderCondition.dll " ;
// 3. 开始编译
CompilerResults results = provider.CompileAssemblyFromSource(cp, code);
// 3.1 显示编译信息
if (results.Errors.Count == 0 )
Console.WriteLine( " \ " { 0 }\ " compiled ok! " , results.CompiledAssembly.Location);
else
{
Console.WriteLine( " Complie Error: " );
foreach (CompilerError error in results.Errors)
Console.WriteLine( " {0} " , error);
}
// 4.执行
Type t = results.CompiledAssembly.GetType( " Nettip.QueryOrderCondition " );
object o = results.CompiledAssembly.CreateInstance( " Nettip.QueryOrderCondition " , false , BindingFlags.Default,
null , new object [] { " Tom " }, CultureInfo.CurrentCulture, null );
t.InvokeMember( " Test " , BindingFlags.Instance | BindingFlags.Public | BindingFlags.InvokeMethod,
null , o, null );
}
}
}