Explorar el Código

添加项目文件。

master
李敢 hace 6 años
padre
commit
888996ce44

+ 16
- 0
EmitCreateDynamicProxy/DDD.cs Ver fichero

@@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;

namespace EmitCreateDynamicProxy
{
class DDD : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;

public string Name { get => _Name; set { _Name = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("uuu")); } }
private string _Name = "";
}
}

+ 228
- 0
EmitCreateDynamicProxy/DynamicProxyGenerator.cs Ver fichero

@@ -0,0 +1,228 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Text;
using System.Threading;

namespace EmitCreateDynamicProxy
{
public class DynamicProxyGenerator
{

private const string DynamicAssemblyName = "DynamicAssembly";//动态程序集名称
private const string DynamicModuleName = "DynamicAssemblyModule";
private const string DynamicModuleDllName = "DynamicAssembly.dll";//动态模块名称
private const string ProxyClassNameFormater = "{0}Proxy";
private const string ModifiedPropertyNamesFieldName = "ModifiedPropertyNames";
private const MethodAttributes GetSetMethodAttributes = MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.CheckAccessOnOverride | MethodAttributes.Virtual | MethodAttributes.HideBySig;

/// <summary>
/// 创建动态程序集,返回AssemblyBuilder
/// </summary>
/// <param name="isSavaDll"></param>
/// <returns></returns>
private static AssemblyBuilder DefineDynamicAssembly(bool isSavaDll = false)
{
//动态创建程序集
AssemblyName DemoName = new AssemblyName(DynamicAssemblyName);
AssemblyBuilderAccess assemblyBuilderAccess = isSavaDll ? AssemblyBuilderAccess.RunAndSave : AssemblyBuilderAccess.Run;
AssemblyBuilder dynamicAssembly = AppDomain.CurrentDomain.DefineDynamicAssembly(DemoName, assemblyBuilderAccess);
return dynamicAssembly;
}

/// <summary>
/// 创建动态模块,返回ModuleBuilder
/// </summary>
/// <param name="isSavaDll"></param>
/// <returns>ModuleBuilder</returns>
private static ModuleBuilder DefineDynamicModule(AssemblyBuilder dynamicAssembly, bool isSavaDll = false)
{
ModuleBuilder moduleBuilder = null;
//动态创建模块
if (isSavaDll)
moduleBuilder = dynamicAssembly.DefineDynamicModule(DynamicModuleName, DynamicModuleDllName);
else
moduleBuilder = dynamicAssembly.DefineDynamicModule(DynamicModuleName);
return moduleBuilder;
}

/// <summary>
/// 创建动态代理类,重写属性Get Set 方法,并监控属性的Set方法,把变更的属性名加入到list集合中,需要监控的属性必须是virtual
/// 如果你想保存修改的属性名和属性值,修改Set方法的IL实现
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="isSavaDynamicModule"></param>
/// <returns></returns>
public static T CreateDynamicProxy<T>(bool isSavaDynamicModule = false)
{
Type modifiedPropertyNamesType = typeof(HashSet<string>);

Type typeNeedProxy = typeof(T);
AssemblyBuilder assemblyBuilder = DefineDynamicAssembly(isSavaDynamicModule);
//动态创建模块
ModuleBuilder moduleBuilder = DefineDynamicModule(assemblyBuilder, isSavaDynamicModule);
string proxyClassName = string.Format(ProxyClassNameFormater, typeNeedProxy.Name);
//动态创建类代理
TypeBuilder typeBuilderProxy = moduleBuilder.DefineType(proxyClassName, TypeAttributes.Public, typeNeedProxy);
//定义一个变量存放属性变更名
FieldBuilder fbModifiedPropertyNames = typeBuilderProxy.DefineField(ModifiedPropertyNamesFieldName, modifiedPropertyNamesType, FieldAttributes.Public);
//定义接口
var pt = typeof(PropertyChangedEventHandler);
typeBuilderProxy.AddInterfaceImplementation(typeof(INotifyPropertyChanged));
var eil = typeBuilderProxy.DefineEvent("PropertyChanged", EventAttributes.None, typeof(PropertyChangedEventHandler));

//add field
var eb = typeBuilderProxy.DefineField("PropertyChanged", typeof(PropertyChangedEventHandler), FieldAttributes.Private);

var compareExchange = GetGenericMethod(typeof(Interlocked), "CompareExchange");// finds the correct method to call.
// thanks to @marc, create the specific method with the correct type
compareExchange = compareExchange.MakeGenericMethod(typeof(PropertyChangedEventHandler));

//add methoed
var mas = MethodAttributes.Public | MethodAttributes.HideBySig
| MethodAttributes.NewSlot | MethodAttributes.SpecialName | MethodAttributes.Virtual | MethodAttributes.Final;
var mb = typeBuilderProxy.DefineMethod("add_PropertyChanged", mas, typeof(void), new Type[] { pt });
mb.DefineParameter(0, ParameterAttributes.Retval, null);
mb.DefineParameter(1, ParameterAttributes.In, "value");
var il = mb.GetILGenerator();
il.DeclareLocal(pt);
il.DeclareLocal(pt);
il.DeclareLocal(pt);
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldfld, eb);
il.Emit(OpCodes.Stloc_0);
var lable = il.DefineLabel();
il.MarkLabel(lable);
il.Emit(OpCodes.Ldloc_0);
il.Emit(OpCodes.Stloc_1);
il.Emit(OpCodes.Ldloc_1);
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Call, typeof(Delegate).GetMethod("Combine", new Type[] { typeof(Delegate), typeof(Delegate) }));
il.Emit(OpCodes.Castclass, typeof(PropertyChangedEventHandler));
il.Emit(OpCodes.Stloc_2);
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldflda, eb);
il.Emit(OpCodes.Ldloc_2);
il.Emit(OpCodes.Ldloc_1);
il.Emit(OpCodes.Call, compareExchange);
il.Emit(OpCodes.Stloc_0);
il.Emit(OpCodes.Ldloc_0);
il.Emit(OpCodes.Ldloc_1);
il.Emit(OpCodes.Bne_Un_S, lable);
il.Emit(OpCodes.Ret);

//remove event
mb = typeBuilderProxy.DefineMethod("remove_PropertyChanged", mas, typeof(void), new Type[] { pt });
mb.DefineParameter(0, ParameterAttributes.Retval, null);
mb.DefineParameter(1, ParameterAttributes.In, "value");

il = mb.GetILGenerator();
il.DeclareLocal(pt);
il.DeclareLocal(pt);
il.DeclareLocal(pt);
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldfld, eb);
il.Emit(OpCodes.Stloc_0);
lable = il.DefineLabel();
il.MarkLabel(lable);
il.Emit(OpCodes.Ldloc_0);
il.Emit(OpCodes.Stloc_1);
il.Emit(OpCodes.Ldloc_1);
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Call, typeof(Delegate).GetMethod("Remove", new Type[] { typeof(Delegate), typeof(Delegate) }));
il.Emit(OpCodes.Castclass, typeof(PropertyChangedEventHandler));
il.Emit(OpCodes.Stloc_2);
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldflda, eb);
il.Emit(OpCodes.Ldloc_2);
il.Emit(OpCodes.Ldloc_1);
il.Emit(OpCodes.Call, compareExchange);
il.Emit(OpCodes.Stloc_0);
il.Emit(OpCodes.Ldloc_0);
il.Emit(OpCodes.Ldloc_1);
il.Emit(OpCodes.Bne_Un_S, lable);
il.Emit(OpCodes.Ret);

/*
* 构造函数 实例化 ModifiedPropertyNames,生成类似于下面的代码
ModifiedPropertyNames = new List<string>();
*/
ConstructorBuilder constructorBuilder = typeBuilderProxy.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, null);
ILGenerator ilgCtor = constructorBuilder.GetILGenerator();
ilgCtor.Emit(OpCodes.Ldarg_0);//加载当前类
ilgCtor.Emit(OpCodes.Newobj, modifiedPropertyNamesType.GetConstructor(new Type[0]));//实例化对象入栈
ilgCtor.Emit(OpCodes.Stfld, fbModifiedPropertyNames);//设置fbModifiedPropertyNames值,为刚入栈的实例化对象
ilgCtor.Emit(OpCodes.Ret);//返回

//获取被代理对象的所有属性,循环属性进行重写
PropertyInfo[] properties = typeNeedProxy.GetProperties();
foreach (PropertyInfo propertyInfo in properties)
{
string propertyName = propertyInfo.Name;
Type typePepropertyInfo = propertyInfo.PropertyType;
//动态创建字段和属性
FieldBuilder fieldBuilder = typeBuilderProxy.DefineField("_" + propertyName, typePepropertyInfo, FieldAttributes.Private);
PropertyBuilder propertyBuilder = typeBuilderProxy.DefineProperty(propertyName, PropertyAttributes.SpecialName, typePepropertyInfo, null);

//重写属性的Get Set方法
var methodGet = typeBuilderProxy.DefineMethod("get_" + propertyName, GetSetMethodAttributes, typePepropertyInfo, Type.EmptyTypes);
var methodSet = typeBuilderProxy.DefineMethod("set_" + propertyName, GetSetMethodAttributes, null, new Type[] { typePepropertyInfo });

//il of get method
var ilGetMethod = methodGet.GetILGenerator();
ilGetMethod.Emit(OpCodes.Ldarg_0);
ilGetMethod.Emit(OpCodes.Ldfld, fieldBuilder);
ilGetMethod.Emit(OpCodes.Ret);
//il of set method
ILGenerator ilSetMethod = methodSet.GetILGenerator();
ilSetMethod.Emit(OpCodes.Ldarg_0);
ilSetMethod.Emit(OpCodes.Ldarg_1);
ilSetMethod.Emit(OpCodes.Stfld, fieldBuilder);
ilSetMethod.Emit(OpCodes.Ldarg_0);
ilSetMethod.Emit(OpCodes.Ldfld, fbModifiedPropertyNames);
ilSetMethod.Emit(OpCodes.Ldstr, propertyInfo.Name);
ilSetMethod.Emit(OpCodes.Callvirt, modifiedPropertyNamesType.GetMethod("Add", new Type[] { typeof(string) }));
ilSetMethod.Emit(OpCodes.Pop);
ilSetMethod.Emit(OpCodes.Ret);

//设置属性的Get Set方法
propertyBuilder.SetGetMethod(methodGet);
propertyBuilder.SetSetMethod(methodSet);
}

//使用动态类创建类型
Type proxyClassType = typeBuilderProxy.CreateType();
//保存动态创建的程序集
if (isSavaDynamicModule)
assemblyBuilder.Save(DynamicModuleDllName);
//创建类实例
var instance = Activator.CreateInstance(proxyClassType);
return (T)instance;
}

/// <summary>
/// 获取属性的变更名称,
/// 此处只检测调用了Set方法的属性,不会检测值是否真的有变
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public static HashSet<string> GetModifiedProperties(object obj)
{
FieldInfo fieldInfo = obj.GetType().GetField(ModifiedPropertyNamesFieldName);
if (fieldInfo == null) return null;
object value = fieldInfo.GetValue(obj);
return value as HashSet<string>;
}

private static MethodInfo GetGenericMethod(Type type, string methodName)
{
var q = from m in type.GetMethods()
where m.Name == methodName && m.IsGenericMethod
select m;
return q.FirstOrDefault();
}
}
}

+ 60
- 0
EmitCreateDynamicProxy/EmitCreateDynamicProxy.csproj Ver fichero

@@ -0,0 +1,60 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{BDA6268A-ADF2-4DA3-8053-81CA4AD007B0}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>EmitCreateDynamicProxy</RootNamespace>
<AssemblyName>EmitCreateDynamicProxy</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<TargetFrameworkProfile>Client</TargetFrameworkProfile>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<PlatformTarget>x86</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<PlatformTarget>x86</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="DDD.cs" />
<Compile Include="DynamicProxyGenerator.cs" />
<Compile Include="Model.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

+ 14
- 0
EmitCreateDynamicProxy/Model.cs Ver fichero

@@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace EmitCreateDynamicProxy
{
public class Model
{
public virtual string LoginName { get; set; }

public virtual string Password { get; set; }
}
}

+ 153
- 0
EmitCreateDynamicProxy/Program.cs Ver fichero

@@ -0,0 +1,153 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;

namespace EmitCreateDynamicProxy
{
class Program
{
static void Main(string[] args)
{
//var command = Proxy.Of<Command>();
//command.Execute();

//Console.WriteLine("Hi, Dennis, great, we got the interceptor works.");
//Console.ReadLine();

Model m = DynamicProxyGenerator.CreateDynamicProxy<Model>(true);
m.LoginName = "ddd";
HashSet<string> modifiedPropertyNames = DynamicProxyGenerator.GetModifiedProperties(m) as HashSet<string>;
}
}

public class Command
{
public virtual void Execute()
{
Console.WriteLine("Command executing...");
Console.WriteLine("Hello Kitty!");
Console.WriteLine("Command executed.");
}
}

public class Interceptor
{
public object Invoke(object @object, string @method, object[] parameters)
{
Console.WriteLine(
string.Format("Interceptor does something before invoke [{0}]...", @method));

var retObj = @object.GetType().GetMethod(@method).Invoke(@object, parameters);

Console.WriteLine(
string.Format("Interceptor does something after invoke [{0}]...", @method));

return retObj;
}
}

public class Proxy
{
public static T Of<T>() where T : class, new()
{
string nameOfAssembly = typeof(T).Name + "ProxyAssembly";
string nameOfModule = typeof(T).Name + "ProxyModule";
string nameOfType = typeof(T).Name + "Proxy";

var assemblyName = new AssemblyName(nameOfAssembly);
var assembly = AppDomain.CurrentDomain
.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
var moduleBuilder = assembly.DefineDynamicModule(nameOfModule);

var typeBuilder = moduleBuilder.DefineType(
nameOfType, TypeAttributes.Public, typeof(T));

InjectInterceptor<T>(typeBuilder);

var t = typeBuilder.CreateType();

return Activator.CreateInstance(t) as T;
}

private static void InjectInterceptor<T>(TypeBuilder typeBuilder)
{
// ---- define fields ----

var fieldInterceptor = typeBuilder.DefineField(
"_interceptor", typeof(Interceptor), FieldAttributes.Private);

// ---- define costructors ----

var constructorBuilder = typeBuilder.DefineConstructor(
MethodAttributes.Public, CallingConventions.Standard, null);
var ilOfCtor = constructorBuilder.GetILGenerator();

ilOfCtor.Emit(OpCodes.Ldarg_0);
ilOfCtor.Emit(OpCodes.Newobj, typeof(Interceptor).GetConstructor(new Type[0]));
ilOfCtor.Emit(OpCodes.Stfld, fieldInterceptor);
ilOfCtor.Emit(OpCodes.Ret);

// ---- define methods ----

var methodsOfType = typeof(T).GetMethods(BindingFlags.Public | BindingFlags.Instance);

for (var i = 0; i < methodsOfType.Length; i++)
{
var method = methodsOfType[i];
var methodParameterTypes =
method.GetParameters().Select(p => p.ParameterType).ToArray();

var methodBuilder = typeBuilder.DefineMethod(
method.Name,
MethodAttributes.Public | MethodAttributes.Virtual,
CallingConventions.Standard,
method.ReturnType,
methodParameterTypes);

var ilOfMethod = methodBuilder.GetILGenerator();
ilOfMethod.Emit(OpCodes.Ldarg_0);
ilOfMethod.Emit(OpCodes.Ldfld, fieldInterceptor);

// create instance of T
ilOfMethod.Emit(OpCodes.Newobj, typeof(T).GetConstructor(new Type[0]));
ilOfMethod.Emit(OpCodes.Ldstr, method.Name);

// build the method parameters
if (methodParameterTypes == null)
{
ilOfMethod.Emit(OpCodes.Ldnull);
}
else
{
var parameters = ilOfMethod.DeclareLocal(typeof(object[]));
ilOfMethod.Emit(OpCodes.Ldc_I4, methodParameterTypes.Length);
ilOfMethod.Emit(OpCodes.Newarr, typeof(object));
ilOfMethod.Emit(OpCodes.Stloc, parameters);

for (var j = 0; j < methodParameterTypes.Length; j++)
{
ilOfMethod.Emit(OpCodes.Ldloc, parameters);
ilOfMethod.Emit(OpCodes.Ldc_I4, j);
ilOfMethod.Emit(OpCodes.Ldarg, j + 1);
ilOfMethod.Emit(OpCodes.Stelem_Ref);
}
ilOfMethod.Emit(OpCodes.Ldloc, parameters);
}

// call Invoke() method of Interceptor
ilOfMethod.Emit(OpCodes.Callvirt, typeof(Interceptor).GetMethod("Invoke"));

// pop the stack if return void
if (method.ReturnType == typeof(void))
{
ilOfMethod.Emit(OpCodes.Pop);
}

// complete
ilOfMethod.Emit(OpCodes.Ret);
}
}
}
}

+ 36
- 0
EmitCreateDynamicProxy/Properties/AssemblyInfo.cs Ver fichero

@@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("EmitCreateDynamicProxy")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("EmitCreateDynamicProxy")]
[assembly: AssemblyCopyright("Copyright © 2013")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]

// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("7dbdf814-4cbd-4fc1-987f-976261539900")]

// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

+ 57
- 0
EmitCreateMembers/EmitCreateMembers.csproj Ver fichero

@@ -0,0 +1,57 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{C4DFB7F2-8C56-4036-B4FF-E56B456B3943}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>EmitCreateMembers</RootNamespace>
<AssemblyName>EmitCreateMembers</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<TargetFrameworkProfile>Client</TargetFrameworkProfile>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<PlatformTarget>x86</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<PlatformTarget>x86</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

+ 138
- 0
EmitCreateMembers/Program.cs Ver fichero

@@ -0,0 +1,138 @@
using System;
using System.Reflection;
using System.Reflection.Emit;

namespace EmitCreateMembers
{
class Program
{
static void Main(string[] args)
{
// specify a new assembly name
var assemblyName = new AssemblyName("Pets");

// create assembly builder
var assemblyBuilder = AppDomain.CurrentDomain
.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave);

// create module builder
var moduleBuilder = assemblyBuilder.DefineDynamicModule("PetsModule", "Pets.dll");

// create type builder for a class
var typeBuilder = moduleBuilder.DefineType("Kitty", TypeAttributes.Public);

// then create whole class structure
CreateKittyClassStructure(typeBuilder);

// then create the whole class type
var classType = typeBuilder.CreateType();

// save assembly
assemblyBuilder.Save("Pets.dll");

Console.WriteLine("Hi, Dennis, a Pets assembly has been generated for you.");
Console.ReadLine();
}

private static void CreateKittyClassStructure(TypeBuilder typeBuilder)
{
// ---- define fields ----

var fieldId = typeBuilder.DefineField(
"_id", typeof(int), FieldAttributes.Private);
var fieldName = typeBuilder.DefineField(
"_name", typeof(string), FieldAttributes.Private);

// ---- define costructors ----

Type objType = Type.GetType("System.Object");
ConstructorInfo objCtor = objType.GetConstructor(new Type[0]);

Type[] constructorArgs = { typeof(int), typeof(string) };

var constructorBuilder = typeBuilder.DefineConstructor(
MethodAttributes.Public, CallingConventions.Standard, constructorArgs);
ILGenerator ilOfCtor = constructorBuilder.GetILGenerator();

ilOfCtor.Emit(OpCodes.Ldarg_0);
ilOfCtor.Emit(OpCodes.Call, objCtor);
ilOfCtor.Emit(OpCodes.Ldarg_0);
ilOfCtor.Emit(OpCodes.Ldarg_1);
ilOfCtor.Emit(OpCodes.Stfld, fieldId);
ilOfCtor.Emit(OpCodes.Ldarg_0);
ilOfCtor.Emit(OpCodes.Ldarg_2);
ilOfCtor.Emit(OpCodes.Stfld, fieldName);
ilOfCtor.Emit(OpCodes.Ret);

// ---- define properties ----

var methodGetId = typeBuilder.DefineMethod(
"GetId", MethodAttributes.Public, typeof(int), null);
var methodSetId = typeBuilder.DefineMethod(
"SetId", MethodAttributes.Public, null, new Type[] { typeof(int) });

var ilOfGetId = methodGetId.GetILGenerator();
ilOfGetId.Emit(OpCodes.Ldarg_0); // this
ilOfGetId.Emit(OpCodes.Ldfld, fieldId);
ilOfGetId.Emit(OpCodes.Ret);

var ilOfSetId = methodSetId.GetILGenerator();
ilOfSetId.Emit(OpCodes.Ldarg_0); // this
ilOfSetId.Emit(OpCodes.Ldarg_1); // the first one in arguments list
ilOfSetId.Emit(OpCodes.Stfld, fieldId);
ilOfSetId.Emit(OpCodes.Ret);

// create Id property
var propertyId = typeBuilder.DefineProperty(
"Id", PropertyAttributes.None, typeof(int), null);
propertyId.SetGetMethod(methodGetId);
propertyId.SetSetMethod(methodSetId);

var methodGetName = typeBuilder.DefineMethod(
"GetName", MethodAttributes.Public, typeof(string), null);
var methodSetName = typeBuilder.DefineMethod(
"SetName", MethodAttributes.Public, null, new Type[] { typeof(string) });

var ilOfGetName = methodGetName.GetILGenerator();
ilOfGetName.Emit(OpCodes.Ldarg_0); // this
ilOfGetName.Emit(OpCodes.Ldfld, fieldName);
ilOfGetName.Emit(OpCodes.Ret);

var ilOfSetName = methodSetName.GetILGenerator();
ilOfSetName.Emit(OpCodes.Ldarg_0); // this
ilOfSetName.Emit(OpCodes.Ldarg_1); // the first one in arguments list
ilOfSetName.Emit(OpCodes.Stfld, fieldName);
ilOfSetName.Emit(OpCodes.Ret);

// create Name property
var propertyName = typeBuilder.DefineProperty(
"Name", PropertyAttributes.None, typeof(string), null);
propertyName.SetGetMethod(methodGetName);
propertyName.SetSetMethod(methodSetName);

// ---- define methods ----

// create ToString() method
var methodToString = typeBuilder.DefineMethod(
"ToString",
MethodAttributes.Virtual | MethodAttributes.Public,
typeof(string),
null);

var ilOfToString = methodToString.GetILGenerator();
var local = ilOfToString.DeclareLocal(typeof(string)); // create a local variable
ilOfToString.Emit(OpCodes.Ldstr, "Id:[{0}], Name:[{1}]");
ilOfToString.Emit(OpCodes.Ldarg_0); // this
ilOfToString.Emit(OpCodes.Ldfld, fieldId);
ilOfToString.Emit(OpCodes.Box, typeof(int)); // boxing the value type to object
ilOfToString.Emit(OpCodes.Ldarg_0); // this
ilOfToString.Emit(OpCodes.Ldfld, fieldName);
ilOfToString.Emit(OpCodes.Call,
typeof(string).GetMethod("Format",
new Type[] { typeof(string), typeof(object), typeof(object) }));
ilOfToString.Emit(OpCodes.Stloc, local); // set local variable
ilOfToString.Emit(OpCodes.Ldloc, local); // load local variable to stack
ilOfToString.Emit(OpCodes.Ret);
}
}
}

+ 36
- 0
EmitCreateMembers/Properties/AssemblyInfo.cs Ver fichero

@@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("EmitCreateMembers")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("EmitCreateMembers")]
[assembly: AssemblyCopyright("Copyright © 2013")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]

// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("03f6f120-a8c3-4286-98e8-ff62a5812cb0")]

// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

+ 57
- 0
EmitIntroduction/EmitIntroduction.csproj Ver fichero

@@ -0,0 +1,57 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{38396364-FAFD-4D67-B265-32B108A797C0}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>EmitIntroduction</RootNamespace>
<AssemblyName>EmitIntroduction</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<TargetFrameworkProfile>Client</TargetFrameworkProfile>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<PlatformTarget>x86</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<PlatformTarget>x86</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

+ 54
- 0
EmitIntroduction/Program.cs Ver fichero

@@ -0,0 +1,54 @@
using System;
using System.Reflection;
using System.Reflection.Emit;

namespace EmitIntroduction
{
class Program
{
static void Main(string[] args)
{
// specify a new assembly name
var assemblyName = new AssemblyName("Kitty");

// create assembly builder
var assemblyBuilder = AppDomain.CurrentDomain
.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave);

// create module builder
var moduleBuilder = assemblyBuilder.DefineDynamicModule("KittyModule", "Kitty.exe");

// create type builder for a class
var typeBuilder = moduleBuilder.DefineType("HelloKittyClass", TypeAttributes.Public);

// create method builder
var methodBuilder = typeBuilder.DefineMethod(
"SayHelloMethod",
MethodAttributes.Public | MethodAttributes.Static,
null,
null);

// then get the method il generator
var il = methodBuilder.GetILGenerator();

// then create the method function
il.Emit(OpCodes.Ldstr, "Hello, Kitty!");
il.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }));
il.Emit(OpCodes.Call, typeof(Console).GetMethod("ReadLine"));
il.Emit(OpCodes.Pop); // we just read something here, throw it.
il.Emit(OpCodes.Ret);

// then create the whole class type
var helloKittyClassType = typeBuilder.CreateType();

// set entry point for this assembly
assemblyBuilder.SetEntryPoint(helloKittyClassType.GetMethod("SayHelloMethod"));

// save assembly
assemblyBuilder.Save("Kitty.exe");

Console.WriteLine("Hi, Dennis, a Kitty assembly has been generated for you.");
Console.ReadLine();
}
}
}

+ 36
- 0
EmitIntroduction/Properties/AssemblyInfo.cs Ver fichero

@@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("EmitIntroduction")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("EmitIntroduction")]
[assembly: AssemblyCopyright("Copyright © 2013")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]

// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("9ecfd944-391f-44be-8ba2-504d10c2c2e4")]

// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

+ 32
- 0
LearningEmit.sln Ver fichero

@@ -0,0 +1,32 @@

Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 2010
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EmitIntroduction", "EmitIntroduction\EmitIntroduction.csproj", "{38396364-FAFD-4D67-B265-32B108A797C0}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EmitCreateMembers", "EmitCreateMembers\EmitCreateMembers.csproj", "{C4DFB7F2-8C56-4036-B4FF-E56B456B3943}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EmitCreateDynamicProxy", "EmitCreateDynamicProxy\EmitCreateDynamicProxy.csproj", "{BDA6268A-ADF2-4DA3-8053-81CA4AD007B0}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x86 = Debug|x86
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{38396364-FAFD-4D67-B265-32B108A797C0}.Debug|x86.ActiveCfg = Debug|x86
{38396364-FAFD-4D67-B265-32B108A797C0}.Debug|x86.Build.0 = Debug|x86
{38396364-FAFD-4D67-B265-32B108A797C0}.Release|x86.ActiveCfg = Release|x86
{38396364-FAFD-4D67-B265-32B108A797C0}.Release|x86.Build.0 = Release|x86
{C4DFB7F2-8C56-4036-B4FF-E56B456B3943}.Debug|x86.ActiveCfg = Debug|x86
{C4DFB7F2-8C56-4036-B4FF-E56B456B3943}.Debug|x86.Build.0 = Debug|x86
{C4DFB7F2-8C56-4036-B4FF-E56B456B3943}.Release|x86.ActiveCfg = Release|x86
{C4DFB7F2-8C56-4036-B4FF-E56B456B3943}.Release|x86.Build.0 = Release|x86
{BDA6268A-ADF2-4DA3-8053-81CA4AD007B0}.Debug|x86.ActiveCfg = Debug|x86
{BDA6268A-ADF2-4DA3-8053-81CA4AD007B0}.Debug|x86.Build.0 = Debug|x86
{BDA6268A-ADF2-4DA3-8053-81CA4AD007B0}.Release|x86.ActiveCfg = Release|x86
{BDA6268A-ADF2-4DA3-8053-81CA4AD007B0}.Release|x86.Build.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

Cargando…
Cancelar
Guardar