.NET内存中动态构造类并重载某函数

开发中,经常需要用到很多容器功能,而容器级别的功能大都是Reflection(类反射)所提供的,本文就是借这个名来看看如何在.NET 内存中动态构造类并重载某函数,具体的例子代码如下:

原类:TestClass

内存中动态生成类: TestClassEx

内存中动态生成类的工厂类:DynamicFactory

接口: ITest

复制以及重载的目标方法:TestMethod

调用集成采用Console方式进行,我们分别看看各个类的代码;

TestClass.cs

public class TestClass
{
private long m_lUsers = 0;
private int m_iUsers = 0;
private string m_strTest = null;
private object m_oTest = null;

public TestClass()
{
m_lUsers++;
m_iUsers++;
m_strTest = "aa";
m_oTest = new object();
}

public long Users
{
set
{
m_lUsers = value;
}
get
{
return m_lUsers;
}
}

public void TestMethod()
{
System.Console.WriteLine("TestMethod: Message output from Emit Console...");

m_lUsers = 50;
m_lUsers += 100;
System.Console.WriteLine("Users :" + Convert.ToString(m_lUsers) + " people in current context");
}

public void EndMethod()
{
System.Console.WriteLine("EndMethod:Ending message logic*****");
}

}

ITest.cs

public interface ITest
{
void TestMethod();
}

DynamicFactory.cs

public class DynamicFactory
{
private AssemblyBuilder assemblyBuilder = null;
private ModuleBuilder moduleBuilder = null;
private TypeBuilder typeBuilder = null;
private ILGenerator generator = null;

public DynamicFactory()
{
}

public Type GenerateClass(Type typeForMirror)
{
this.GenerateAssembly();

//build a type
this.typeBuilder = moduleBuilder.DefineType("TestClassEx",
TypeAttributes.Public | TypeAttributes.BeforeFieldInit,
typeForMirror, new Type[] { typeof(ITest) });

this.GenerateConstruct(typeBuilder);
this.BuildFields(typeForMirror);

this.BuildMethod(typeForMirror);

Type typeReturn = this.typeBuilder.CreateType(); //Close the type
assemblyBuilder.Save("ExtendingAssembly.dll");
return typeReturn;
}

private void BuildFields(Type typeForMirror)
{
FieldInfo[] fieldInfos = typeForMirror.GetFields(BindingFlags.NonPublic | BindingFlags.Public);
for (int i = 0; i < fieldInfos.Length; i++)
{
FieldInfo fi = fieldInfos[i];
typeBuilder.DefineField(fi.Name, fi.FieldType, fi.Attributes);
}
}

private void GenerateAssembly()
{
AppDomain currentDomain = Thread.GetDomain();
AssemblyName assemblyName = new AssemblyName();
assemblyName.Name = "Extending";
assemblyBuilder = currentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave);
this.moduleBuilder = assemblyBuilder.DefineDynamicModule(
"ExtendingAssembly",
"ExtendingAssembly.dll");
}

private void GenerateConstruct(TypeBuilder typeBuilder)
{
ConstructorBuilder constructorBuilder = typeBuilder.DefineConstructor(
MethodAttributes.Public,
CallingConventions.Standard,
System.Type.EmptyTypes);

this.generator = constructorBuilder.GetILGenerator();
generator.Emit(OpCodes.Ldarg_0);
generator.Emit(OpCodes.Call, typeBuilder.BaseType.GetConstructor(System.Type.EmptyTypes));
generator.Emit(OpCodes.Ret);
}

/// <summary>
/// Attention: here we need to overload the specified TestMethod function for our EmitConsole project.
/// So the MethodAttributes.Virtual is necessary when we rebuild this function in memory.
/// </summary>
/// <param name="typeForMirror"></param>
private void BuildMethod(Type typeForMirror)
{
// Now, let's build a method and add a custom attribute to it.
MethodBuilder methodBuilder = typeBuilder.DefineMethod("TestMethod",
MethodAttributes.Public | MethodAttributes.HideBySig |
MethodAttributes.Virtual | MethodAttributes.NewSlot,
null,
new Type[] {});

this.generator = methodBuilder.GetILGenerator();

generator.Emit(OpCodes.Ldarg_0);
generator.Emit(OpCodes.Call, typeForMirror.GetMethod("TestMethod"));

generator.Emit(OpCodes.Ldarg_0);
generator.Emit(OpCodes.Call, typeForMirror.GetMethod("EndMethod"));

generator.Emit(OpCodes.Ret);
}

}

console的集成类program.cs:

class Program
{
static void Main(string[] args)
{
DynamicFactory df = new DynamicFactory();

// type for mirroring testing method
Type typeMirror = df.GenerateClass(typeof(TestClass));

object o = Activator.CreateInstance(typeMirror);
TestClass tc = (TestClass)o;
tc.TestMethod();

ITest it = (ITest)Activator.CreateInstance(typeMirror);
it.TestMethod();

System.Console.WriteLine("Ending finally...");
}
}

从最后的运行效果大家可以分析看看,采用TestClass强转后的instance与不转使用interface来直接集成的program最后的结果不一样,自己可以分析看看是啥原因产生的。

本文中未提及到的Enum, Property等的复制产生可以参照:http://www.codeproject.com/KB/cs/DLR.aspx

能够在内存中动态重组类的作用非常大,可以实现基于AOP的拦截,实现基于标注的各类应用譬如自动组装Transaction、依赖注入等众多的高级应用,对于编写框架应用作用无疑巨大。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值