public static T Create <T>(string objectId, IProxyClient client) { ; if (_runtimeProxyTypes.ContainsKey(typeof(T))) { return((T)Activator.CreateInstance(_runtimeProxyTypes[typeof(T)], objectId, client)); } // Verify type is interface if (!typeof(T).IsInterface) { throw new InvalidOperationException("Generic argument must be an interface."); } TypeBuilder typeBuilder = _moduleBuilder.DefineType($"{typeof(T).Name}Proxy", TypeAttributes.Public); // Define parent and interface typeBuilder.SetParent(typeof(RuntimeProxy)); typeBuilder.CreatePassThroughConstructors(typeof(RuntimeProxy)); typeBuilder.AddInterfaceImplementation(typeof(T)); // Implement events foreach (var eventInfo in ObjectDescriptor.GetEvents <T>()) { Expression <Func <RuntimeTypeHandle, object> > getTypeFromHandle = t => Type.GetTypeFromHandle(t); EventBuilder eventBuilder = typeBuilder.DefineEvent(eventInfo.Value.Name, eventInfo.Value.Attributes, eventInfo.Value.EventHandlerType); FieldBuilder eventFieldBuilder = typeBuilder.DefineField($"_{eventInfo.Value.Name}", eventInfo.Value.EventHandlerType, FieldAttributes.Private); // Implement event handler add method // add { ... } { MethodInfo addMethodInfo = eventInfo.Value.GetAddMethod(); MethodBuilder getMb = typeBuilder.DefineMethod(addMethodInfo.Name, MethodAttributes.Public | MethodAttributes.Virtual, typeof(void), new Type[] { eventInfo.Value.EventHandlerType }); ILGenerator ilGenerator = getMb.GetILGenerator(); Type ehType = eventInfo.Value.EventHandlerType; LocalBuilder typeLb = ilGenerator.DeclareLocal(typeof(Type), true); LocalBuilder objectLb = ilGenerator.DeclareLocal(typeof(object), true); LocalBuilder retLb = ilGenerator.DeclareLocal(typeof(bool), true); // _event += value; Expression <Func <Delegate, object> > combine = d => Delegate.Combine(d, d); ilGenerator.Emit(OpCodes.Ldarg_0); ilGenerator.Emit(OpCodes.Ldarg_0); ilGenerator.Emit(OpCodes.Ldfld, eventFieldBuilder); ilGenerator.Emit(OpCodes.Ldarg_1); ilGenerator.EmitCall(OpCodes.Call, combine.GetMethodInfo(), null); ilGenerator.Emit(OpCodes.Castclass, ehType); ilGenerator.Emit(OpCodes.Stfld, eventFieldBuilder); // this.Subscribe(eventId, value); Expression <Func <RuntimeProxy, object> > addEventHandler = o => o.Subscribe(null, null); ilGenerator.Emit(OpCodes.Ldarg_0); ilGenerator.Emit(OpCodes.Ldstr, eventInfo.Key); ilGenerator.Emit(OpCodes.Ldarg_0); ilGenerator.Emit(OpCodes.Ldfld, eventFieldBuilder); ilGenerator.EmitCall(OpCodes.Callvirt, addEventHandler.GetMethodInfo(), null); ilGenerator.Emit(OpCodes.Stloc_2); ilGenerator.Emit(OpCodes.Ret); typeBuilder.DefineMethodOverride(getMb, addMethodInfo); } // Implement event handler remove method // remove { ... } { MethodInfo removeMethodInfo = eventInfo.Value.GetRemoveMethod(); MethodBuilder getMb = typeBuilder.DefineMethod(removeMethodInfo.Name, MethodAttributes.Public | MethodAttributes.Virtual, typeof(void), new Type[] { eventInfo.Value.EventHandlerType }); ILGenerator ilGenerator = getMb.GetILGenerator(); Type ehType = eventInfo.Value.EventHandlerType; LocalBuilder typeLb = ilGenerator.DeclareLocal(typeof(Type), true); LocalBuilder objectLb = ilGenerator.DeclareLocal(typeof(object), true); LocalBuilder retLb = ilGenerator.DeclareLocal(typeof(bool), true); // _event -= value; Expression <Func <Delegate, object> > remove = d => Delegate.Remove(d, d); ilGenerator.Emit(OpCodes.Ldarg_0); ilGenerator.Emit(OpCodes.Ldarg_0); ilGenerator.Emit(OpCodes.Ldfld, eventFieldBuilder); ilGenerator.Emit(OpCodes.Ldarg_1); ilGenerator.EmitCall(OpCodes.Call, remove.GetMethodInfo(), null); ilGenerator.Emit(OpCodes.Castclass, ehType); ilGenerator.Emit(OpCodes.Stfld, eventFieldBuilder); // this.Unsubscribe(eventId, value); Expression <Func <RuntimeProxy, object> > removeEventHandler = o => o.Unsubscribe(null, null); ilGenerator.Emit(OpCodes.Ldarg_0); ilGenerator.Emit(OpCodes.Ldstr, eventInfo.Key); ilGenerator.Emit(OpCodes.Ldarg_0); ilGenerator.Emit(OpCodes.Ldfld, eventFieldBuilder); ilGenerator.EmitCall(OpCodes.Callvirt, removeEventHandler.GetMethodInfo(), null); ilGenerator.Emit(OpCodes.Stloc_2); ilGenerator.Emit(OpCodes.Ret); typeBuilder.DefineMethodOverride(getMb, removeMethodInfo); } } // Implement properties foreach (var propertyInfo in ObjectDescriptor.GetProperties <T>()) { Expression <Func <RuntimeTypeHandle, object> > getTypeFromHandle = t => Type.GetTypeFromHandle(t); PropertyBuilder propertyBuilder = typeBuilder.DefineProperty(propertyInfo.Value.Name, propertyInfo.Value.Attributes, propertyInfo.Value.PropertyType, null); if (propertyInfo.Value.CanRead) { MethodInfo getMethodInfo = propertyInfo.Value.GetGetMethod(); MethodBuilder getMb = typeBuilder.DefineMethod(getMethodInfo.Name, MethodAttributes.Public | MethodAttributes.Virtual, propertyInfo.Value.PropertyType, Type.EmptyTypes); ILGenerator ilGenerator = getMb.GetILGenerator(); LocalBuilder typeLb = ilGenerator.DeclareLocal(typeof(Type), true); LocalBuilder outObjectLb = ilGenerator.DeclareLocal(typeof(object), true); LocalBuilder retLb = ilGenerator.DeclareLocal(typeof(bool), true); // obj = this.GetValue(propertyId, out result); object obj = null; Expression <Func <RuntimeProxy, object> > setValue = o => o.GetValue(null, out obj); ilGenerator.Emit(OpCodes.Ldarg_0); ilGenerator.Emit(OpCodes.Ldstr, propertyInfo.Key); ilGenerator.Emit(OpCodes.Ldloca_S, 1); ilGenerator.EmitCall(OpCodes.Callvirt, setValue.GetMethodInfo(), null); ilGenerator.Emit(OpCodes.Stloc_2); // Handle value return types Expression <Func <object, object> > createInstance = a => Activator.CreateInstance(a.GetType()); ilGenerator.Emit(OpCodes.Ldloc_1); if (propertyInfo.Value.PropertyType.IsValueType) { Label retisnull = ilGenerator.DefineLabel(); Label endofif = ilGenerator.DefineLabel(); // Create instance if value is null ilGenerator.Emit(OpCodes.Ldnull); ilGenerator.Emit(OpCodes.Ceq); ilGenerator.Emit(OpCodes.Brtrue_S, retisnull); ilGenerator.Emit(OpCodes.Ldloc_1); ilGenerator.Emit(OpCodes.Unbox_Any, propertyInfo.Value.PropertyType); ilGenerator.Emit(OpCodes.Br_S, endofif); ilGenerator.MarkLabel(retisnull); ilGenerator.Emit(OpCodes.Ldtoken, propertyInfo.Value.PropertyType); ilGenerator.EmitCall(OpCodes.Call, getTypeFromHandle.GetMethodInfo(), null); ilGenerator.EmitCall(OpCodes.Call, createInstance.GetMethodInfo(), null); ilGenerator.Emit(OpCodes.Unbox_Any, propertyInfo.Value.PropertyType); ilGenerator.MarkLabel(endofif); } ilGenerator.Emit(OpCodes.Ret); propertyBuilder.SetGetMethod(getMb); typeBuilder.DefineMethodOverride(getMb, getMethodInfo); } if (propertyInfo.Value.CanWrite) { MethodInfo setMethodInfo = propertyInfo.Value.GetSetMethod(); MethodBuilder setMb = typeBuilder.DefineMethod(setMethodInfo.Name, MethodAttributes.Public | MethodAttributes.Virtual, typeof(void), new Type[] { propertyInfo.Value.PropertyType }); ILGenerator ilGenerator = setMb.GetILGenerator(); LocalBuilder typeLb = ilGenerator.DeclareLocal(typeof(Type), true); LocalBuilder objectLb = ilGenerator.DeclareLocal(propertyInfo.Value.PropertyType, true); LocalBuilder retLb = ilGenerator.DeclareLocal(typeof(bool), true); // this.SetValue(propertyId, value); ilGenerator.Emit(OpCodes.Ldarg_1); ilGenerator.Emit(OpCodes.Stloc_1); Expression <Func <RuntimeProxy, object> > setValue = o => o.SetValue(null, null); ilGenerator.Emit(OpCodes.Ldarg_0); ilGenerator.Emit(OpCodes.Ldstr, propertyInfo.Key); ilGenerator.Emit(OpCodes.Ldloc_1); if (propertyInfo.Value.PropertyType.IsValueType) { ilGenerator.Emit(OpCodes.Box, propertyInfo.Value.PropertyType); } ilGenerator.EmitCall(OpCodes.Callvirt, setValue.GetMethodInfo(), null); ilGenerator.Emit(OpCodes.Stloc_2); ilGenerator.Emit(OpCodes.Ret); propertyBuilder.SetSetMethod(setMb); typeBuilder.DefineMethodOverride(setMb, setMethodInfo); } } // Implement methods foreach (var methodInfo in ObjectDescriptor.GetMethods <T>()) { object obj = null; Expression <Func <RuntimeProxy, object> > invoke = o => o.Invoke(null, null, out obj); Expression <Func <object, object> > createInstance = a => Activator.CreateInstance(a.GetType()); Expression <Func <RuntimeTypeHandle, object> > getTypeFromHandle = t => Type.GetTypeFromHandle(t); Expression <Func <List <object>, object> > listToArray = l => l.ToArray(); Expression <Action <List <object> > > listAdd = l => l.Add(new object()); var parameterInfoArray = methodInfo.Value.GetParameters(); var genericArgumentArray = methodInfo.Value.GetGenericArguments(); MethodBuilder mb = typeBuilder.DefineMethod(methodInfo.Value.Name, MethodAttributes.Public | MethodAttributes.Virtual, methodInfo.Value.ReturnType, parameterInfoArray.Select(pi => pi.ParameterType).ToArray()); if (genericArgumentArray.Any()) { mb.DefineGenericParameters(genericArgumentArray.Select(s => s.Name).ToArray()); } ILGenerator ilGenerator = mb.GetILGenerator(); LocalBuilder typeLb = ilGenerator.DeclareLocal(typeof(Type), true); LocalBuilder paramsLb = ilGenerator.DeclareLocal(typeof(List <object>), true); LocalBuilder resultLb = ilGenerator.DeclareLocal(typeof(object), true); LocalBuilder retLb = ilGenerator.DeclareLocal(typeof(bool), true); // Create method argument array ilGenerator.Emit(OpCodes.Newobj, typeof(List <object>).GetConstructor(Type.EmptyTypes)); ilGenerator.Emit(OpCodes.Stloc_1); int i = 0; foreach (ParameterInfo pi in methodInfo.Value.GetParameters()) { i++; ilGenerator.Emit(OpCodes.Ldloc_1); ilGenerator.Emit(OpCodes.Ldarg, i); if (pi.ParameterType.IsValueType) { ilGenerator.Emit(OpCodes.Box, pi.ParameterType); } ilGenerator.EmitCall(OpCodes.Callvirt, listAdd.GetMethodInfo(), null); } // this.Invoke(methodId, args, out result); ilGenerator.Emit(OpCodes.Ldarg_0); ilGenerator.Emit(OpCodes.Ldstr, methodInfo.Key); ilGenerator.Emit(OpCodes.Ldloc_1); ilGenerator.EmitCall(OpCodes.Callvirt, listToArray.GetMethodInfo(), null); ilGenerator.Emit(OpCodes.Ldloca_S, 2); ilGenerator.EmitCall(OpCodes.Callvirt, invoke.GetMethodInfo(), null); ilGenerator.Emit(OpCodes.Stloc_3); if (methodInfo.Value.ReturnType != typeof(void)) { ilGenerator.Emit(OpCodes.Ldloc_2); // Handle value return types if (methodInfo.Value.ReturnType.IsValueType) { Label retisnull = ilGenerator.DefineLabel(); Label endofif = ilGenerator.DefineLabel(); // Create instance if value is null ilGenerator.Emit(OpCodes.Ldnull); ilGenerator.Emit(OpCodes.Ceq); ilGenerator.Emit(OpCodes.Brtrue_S, retisnull); ilGenerator.Emit(OpCodes.Ldloc_2); ilGenerator.Emit(OpCodes.Unbox_Any, methodInfo.Value.ReturnType); ilGenerator.Emit(OpCodes.Br_S, endofif); ilGenerator.MarkLabel(retisnull); ilGenerator.Emit(OpCodes.Ldtoken, methodInfo.Value.ReturnType); ilGenerator.EmitCall(OpCodes.Call, getTypeFromHandle.GetMethodInfo(), null); ilGenerator.EmitCall(OpCodes.Call, createInstance.GetMethodInfo(), null); ilGenerator.Emit(OpCodes.Unbox_Any, methodInfo.Value.ReturnType); ilGenerator.MarkLabel(endofif); } } ilGenerator.Emit(OpCodes.Ret); typeBuilder.DefineMethodOverride(mb, methodInfo.Value); } // Create and store new type instance Type type = typeBuilder.CreateType(); _runtimeProxyTypes.Add(typeof(T), type); return((T)Activator.CreateInstance(type, objectId, client)); }