internal Factory(DynamicAssembly ab) { this.assembly = ab; this.OfProxies = new Proxies(this); this.OfStubs = new Stubs(this); this.Dynamic = new Dynamic(this); }
public Func <TWrappedType, TState, TWrappedType> Create() { var tb = this.ab.Module.DefineType(Guid.NewGuid().ToString(), TypeAttributes.Class); var abstractType = typeof(TWrappedType); tb.AddInterfaceImplementation(abstractType); var postEntryDelegateField = this.postEntry == null ? null : tb.DefineField( nameof(this.postEntry), this.postEntry.GetType(), FieldAttributes.Private | FieldAttributes.Static); var preExitDelegateField = this.preExit == null ? null : tb.DefineField( nameof(this.preExit), this.preExit.GetType(), FieldAttributes.Private | FieldAttributes.Static); var targetField = tb.DefineField( "target", abstractType, FieldAttributes.InitOnly | FieldAttributes.Private); var stateField = tb.DefineField( "state", typeof(TState), FieldAttributes.InitOnly | FieldAttributes.Private); { var constructor = tb.DefineConstructor( MethodAttributes.Public, CallingConventions.HasThis, new Type[] { targetField.FieldType, stateField.FieldType }); var il = constructor.GetILGenerator(); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Call, typeof(object).GetConstructor(Type.EmptyTypes)); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Stfld, targetField); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldarg_2); il.Emit(OpCodes.Stfld, stateField); il.Emit(OpCodes.Ret); } this.ab.ImplementAbstractMethods(tb, abstractType, ImplementAsDecorator, false); var typeInfo = tb.CreateTypeInfo(); var runtimePostEntryField = typeInfo.GetField(nameof(this.postEntry), BindingFlags.Static | BindingFlags.NonPublic); runtimePostEntryField?.SetValue(typeInfo, this.postEntry); var runtimePreExitField = typeInfo.GetField(nameof(this.preExit), BindingFlags.Static | BindingFlags.NonPublic); runtimePreExitField?.SetValue(typeInfo, this.preExit); return((target, state) => (TWrappedType)this.ab.ActivateInstance(typeInfo, target, state)); void ImplementAsDecorator(MethodInfo method, ILGenerator il) { il.DeclareLocal(typeof(object[])); if (method.ReturnType != typeof(void)) { il.DeclareLocal(method.ReturnType); } var parameters = method.GetParameters(); var length = parameters.Length; if (postEntryDelegateField != null) { il.Emit(OpCodes.Ldc_I4, length); il.Emit(OpCodes.Newarr, typeof(object)); for (int i = 0; i < length; ++i) { il.Emit(OpCodes.Dup); il.Emit(OpCodes.Ldc_I4, i); il.Emit(OpCodes.Ldarg, (short)(i + 1)); DynamicAssembly.TypeErase(il, parameters[i].ParameterType); il.Emit(OpCodes.Stelem_Ref); } il.Emit(OpCodes.Stloc_0); il.Emit(OpCodes.Ldsfld, postEntryDelegateField); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, targetField); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, stateField); il.Emit(OpCodes.Ldloc_0); il.EmitCall(OpCodes.Callvirt, postEntryDelegateField.FieldType.GetMethod("Invoke"), null); for (int i = 0; i < length; ++i) { il.Emit(OpCodes.Ldloc_0); il.Emit(OpCodes.Ldc_I4, i); il.Emit(OpCodes.Ldelem_Ref); DynamicAssembly.TypeRestore(il, parameters[i].ParameterType); il.Emit(OpCodes.Starg, (short)(i + 1)); } } il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, targetField); DynamicAssembly.UnrollParameterLoading(il, 1, length); il.EmitCall(OpCodes.Callvirt, method, null); if (preExitDelegateField != null) { il.Emit(OpCodes.Stloc_1); il.Emit(OpCodes.Ldsfld, preExitDelegateField); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, targetField); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, stateField); il.Emit(OpCodes.Ldloc_1); DynamicAssembly.TypeErase(il, method.ReturnType); il.EmitCall(OpCodes.Callvirt, preExitDelegateField.FieldType.GetMethod("Invoke"), null); DynamicAssembly.TypeRestore(il, method.ReturnType); } il.Emit(OpCodes.Ret); } }
internal InstantiatedStatefulBuilder(DynamicAssembly ab) { this.ab = ab; }
internal InstantiatedStatelessBuilder(DynamicAssembly ab) { this.ab = ab; this.builder = new InstantiatedStatefulBuilder <TWrappedType, object>(ab); }
internal ProxyBuilder(DynamicAssembly ab) { this.ab = ab; }
internal Proxies(Factory factory) { this.factory = factory; this.ab = this.factory.Assembly; }