Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // The proxy generator, I assume that the error is buried along the lines emitting the IL code
- public static class ProxyGenerator
- {
- public static T Create<T>(object obj, IInterception interception)
- {
- Type type = obj.GetType();
- TypeBuilder proxy = DefineProxy(type);
- FieldBuilder wrappedField = DefinePrivateField(proxy, "wrappedObject", type);
- FieldBuilder interceptionField = DefinePrivateField(proxy, "interception", interception.GetType());
- DefineConstructor(proxy, wrappedField, interceptionField);
- DefineInterfaceMethods(type, proxy, wrappedField, interceptionField);
- return (T) Activator.CreateInstance(proxy.CreateType(), obj, interception);
- }
- private static TypeBuilder DefineProxy(Type type)
- {
- var assemblyName = new AssemblyName {Name = "GeneratedProxyAssembly"};
- AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(
- assemblyName, AssemblyBuilderAccess.Run);
- ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("GeneratedProxyModule");
- return moduleBuilder.DefineType(
- type.Name + "Proxy",
- type.Attributes,
- typeof (object),
- type.GetInterfaces());
- }
- private static FieldBuilder DefinePrivateField(TypeBuilder typeBuilder, string fieldName, Type fieldType)
- {
- return typeBuilder.DefineField(fieldName, fieldType, FieldAttributes.Private);
- }
- private static void DefineConstructor(TypeBuilder typeBuilder, params FieldBuilder[] parameters)
- {
- ConstructorBuilder ctor = typeBuilder.DefineConstructor(
- MethodAttributes.Public, CallingConventions.Standard, parameters.Select(f => f.FieldType).ToArray());
- // Emit constructor
- ILGenerator g = ctor.GetILGenerator();
- // Load "this" pointer and call base constructor
- g.Emit(OpCodes.Ldarg_0);
- g.Emit(OpCodes.Call, typeof(object).GetConstructor(new Type[0]));
- // Store parameters in private fields
- for (int i = 0; i < parameters.Length; i++)
- {
- // Load "this" pointer and parameter and store paramater in private field
- g.Emit(OpCodes.Ldarg_0);
- g.Emit(OpCodes.Ldarg, i + 1);
- g.Emit(OpCodes.Stfld, parameters[i]);
- }
- // Return
- g.Emit(OpCodes.Ret);
- }
- private static void DefineInterfaceMethods(Type type, TypeBuilder proxy, FieldInfo wrappedField, FieldInfo interceptionField)
- {
- // Loop through all interface methods
- foreach (MethodInfo interfaceMethod in type.GetInterfaces().SelectMany(i => i.GetMethods()))
- {
- MethodInfo method = type.GetMethod(interfaceMethod.Name);
- MethodBuilder methodBuilder = proxy.DefineMethod(
- method.Name,
- method.Attributes,
- method.ReturnType,
- method.GetParameters().Select(p => p.ParameterType).ToArray());
- // Emit method
- ILGenerator g = methodBuilder.GetILGenerator();
- // Intercept before
- EmitMethodCallOnMember(g, interceptionField, "Before", false);
- // Delegate method call
- EmitMethodCallOnMember(g, wrappedField, method.Name, true);
- // Intercept before
- EmitMethodCallOnMember(g, interceptionField, "After", false);
- // Return
- g.Emit(OpCodes.Ret);
- }
- }
- private static void EmitMethodCallOnMember(ILGenerator g, FieldInfo field, string methodName, bool delegateParameters)
- {
- // Load "this" pointer to get address of field
- g.Emit(OpCodes.Ldarg_0);
- g.Emit(OpCodes.Ldflda, field);
- MethodInfo method = field.FieldType.GetMethod(methodName);
- if (delegateParameters)
- {
- // Load method parameters
- for (int i = 0; i < method.GetParameters().Length; i++)
- {
- g.Emit(OpCodes.Ldarg, i + 1);
- }
- }
- // Emit call
- g.Emit(OpCodes.Call, method);
- }
- }
- // Some infrastructure
- public interface IInterception
- {
- void Before();
- void After();
- }
- public class LogInterception : IInterception
- {
- public void Before()
- {
- Console.WriteLine("Before ... ");
- }
- public void After()
- {
- Console.WriteLine("... After");
- }
- }
- public interface ITest
- {
- string DoSomething(string s1, string s2);
- }
- public class Test : ITest
- {
- public string DoSomething(string s1, string s2)
- {
- Console.WriteLine("... doing something ...");
- return s1 + s2;
- }
- }
- // The test program, expected output is down below
- internal class Program
- {
- internal static void Main(string[] args)
- {
- var test = new Test();
- var proxy = ProxyGenerator.Create<ITest>(test, new LogInterception());
- Console.WriteLine(test.DoSomething("Hello", " World"));
- Console.WriteLine("----------------------------------------");
- Console.WriteLine(proxy.DoSomething("Hello", " World"));
- Console.ReadKey();
- }
- }
- // The output
- // ... doing something ...
- // Hello World
- // ----------------------------------------
- // Before ...
- // ... doing something ...
- // ... After
- // Hello World
Advertisement
Add Comment
Please, Sign In to add comment