private Type CreateProxyClass(Type rootInterfaceType, Type interfaceType, string path) { var serviceDescription = serviceDescriptionBuilder.Build(interfaceType); path = path ?? serviceDescription.Name; var typeBuilder = DeclareType(interfaceType); var fieldCache = new ProxyClassFieldCache(typeBuilder); var classContext = new ProxyClassBuildingContext(rootInterfaceType, path, typeBuilder, fieldCache); foreach (var methodDesc in serviceDescription.Methods) { CreateMethod(classContext, path, methodDesc); } CreateConstructor(classContext, path, serviceDescription); return(typeBuilder.CreateType()); }
private KeyValuePair <string, ImplementationCreationInfo> ConvertPair(InterfaceImplementationTypePair pair) { var serviceName = pair.Interface.GetServiceName(); if (!pair.Interface.IsAssignableFrom(pair.ImplementationType)) { throw new ArgumentException(string.Format("Given implementation for a '{0}' service ({1}) does not implement its interface", serviceName, pair.ImplementationType.FullName)); } var constructor = FindLargestAppropriateConstructor(pair.ImplementationType); if (constructor == null) { throw new ArgumentException(string.Format("No appropriate constructor found for {0}", pair.ImplementationType.FullName)); } var creationInfo = new ImplementationCreationInfo { Constructor = constructor, Description = serviceDescriptionBuilder.Build(pair.Interface) }; return(new KeyValuePair <string, ImplementationCreationInfo>(pair.Interface.GetServiceName(), creationInfo)); }
public void Setup() { serviceDescription = new ServiceDescription(typeof(IMyService), "MyService", new SubserviceDescription[0], new[] {new MethodDescription(typeof(void), "DoSomething", new MethodParameterDescription[0])}); serviceDescriptionBuilder = Substitute.For<IServiceDescriptionBuilder>(); serviceDescriptionBuilder.Build(typeof(IMyService)).Returns(serviceDescription); container = new ServiceImplementationContainer(serviceDescriptionBuilder); }
private Type CreateProxyClass(Type rootType, Type type, string path) { var serviceDescription = serviceDescriptionBuilder.Build(type); path = path ?? serviceDescription.Name; var typeBuilder = moduleBuilder.DefineType("__rpc_proxy_" + type.FullName + "_" + classNameDisambiguator++, TypeAttributes.Public | TypeAttributes.Sealed | TypeAttributes.Class, typeof(object), new[] { type }); #region Emit Fields var processorField = typeBuilder.DefineField("methodCallProcessor", typeof(IOutgoingMethodCallProcessor), FieldAttributes.Private | FieldAttributes.InitOnly); var scopeField = typeBuilder.DefineField("scope", typeof(string), FieldAttributes.Private | FieldAttributes.InitOnly); var timeoutSettingsField = typeBuilder.DefineField("timeoutSettings", typeof(TimeoutSettings), FieldAttributes.Private | FieldAttributes.InitOnly); #endregion #region Begin Emit Constructor var constructorBuilder = typeBuilder.DefineConstructor( MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName, CallingConventions.Standard, ConstructorParameterTypes); var baseConstructor = typeof(object).GetConstructor(Type.EmptyTypes); var cil = constructorBuilder.GetILGenerator(); cil.Emit(OpCodes.Ldarg_0); cil.Emit(OpCodes.Call, baseConstructor); cil.Emit(OpCodes.Ldarg_0); cil.Emit(OpCodes.Ldarg_1); cil.Emit(OpCodes.Stfld, processorField); cil.Emit(OpCodes.Ldarg_0); cil.Emit(OpCodes.Ldarg_2); cil.Emit(OpCodes.Stfld, scopeField); cil.Emit(OpCodes.Ldarg_0); cil.Emit(OpCodes.Ldarg_3); cil.Emit(OpCodes.Stfld, timeoutSettingsField); #endregion foreach (var subserviceDesc in serviceDescription.Subservices) { #region Emit Subservice Property var proxyClass = CreateProxyClass(rootType, subserviceDesc.Service.Type, path + "/" + subserviceDesc.Name); var fieldBuilder = typeBuilder.DefineField("_" + subserviceDesc.Name, proxyClass, FieldAttributes.Private | FieldAttributes.InitOnly); cil.Emit(OpCodes.Ldarg_0); cil.Emit(OpCodes.Ldarg_1); cil.Emit(OpCodes.Ldarg_2); cil.Emit(OpCodes.Ldarg_3); cil.Emit(OpCodes.Newobj, proxyClass.GetConstructor(ConstructorParameterTypes)); cil.Emit(OpCodes.Stfld, fieldBuilder); var methodBuilder = typeBuilder.DefineMethod("get_" + subserviceDesc.Name, MethodAttributes.Public | MethodAttributes.Final | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.NewSlot | MethodAttributes.Virtual, subserviceDesc.Service.Type, Type.EmptyTypes); methodBuilder.SetImplementationFlags(MethodImplAttributes.Managed); var il = methodBuilder.GetILGenerator(); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, fieldBuilder); il.Emit(OpCodes.Ret); var propertyBuilder = typeBuilder.DefineProperty(subserviceDesc.Name, PropertyAttributes.None, subserviceDesc.Service.Type, Type.EmptyTypes); propertyBuilder.SetGetMethod(methodBuilder); #endregion } #region End Emit Constructor cil.Emit(OpCodes.Ret); #endregion foreach (var methodDesc in serviceDescription.Methods) { #region Emit Method var parameterTypes = methodDesc.Parameters.Select(x => x.Way == MethodParameterWay.Val ? x.Type : x.Type.MakeByRefType()).ToArray(); var dynamicMethod = EmitDynamicMethod(rootType, path, methodDesc, parameterTypes, codecContainer); dynamicMethods.Add(dynamicMethod); var dynamicMethodPointer = MethodHelpers.ExtractDynamicMethodPointer(dynamicMethod); var methodBuilder = typeBuilder.DefineMethod(methodDesc.Name, MethodAttributes.Public | MethodAttributes.Final | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual, dynamicMethod.ReturnType, parameterTypes); methodBuilder.SetImplementationFlags(MethodImplAttributes.Managed); var il = methodBuilder.GetILGenerator(); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, processorField); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, scopeField); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, timeoutSettingsField); for (int i = 0; i < methodDesc.Parameters.Count; i++) { il.Emit(OpCodes.Ldarg, i + 1); } il.Emit_Ldc_IntPtr(dynamicMethodPointer); il.EmitCalli(OpCodes.Calli, CallingConventions.Standard, dynamicMethod.ReturnType, dynamicMethod.GetParameters().Select(x => x.ParameterType).ToArray(), null); il.Emit(OpCodes.Ret); #endregion } return(typeBuilder.CreateType()); }