Type complete_singleton_type(singleton_entry entry) { TypeBuilder type_builder = entry.m_type_builder; XSingletonTypeDescription2 xSingletonType = entry.m_xType; string sSingletonName = to_cts_name(xSingletonType.getName()); // Create the private default constructor ConstructorBuilder ctor_builder = type_builder.DefineConstructor((MethodAttributes.Private | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName), CallingConventions.Standard, null); ILGenerator ilGen = ctor_builder.GetILGenerator(); ilGen.Emit(OpCodes.Ldarg_0); // push this ilGen.Emit(OpCodes.Call, type_builder.BaseType.GetConstructor(new Type[0])); ilGen.Emit(OpCodes.Ret); // obtain the interface which makes up this service, it is the return // type of the constructor functions XInterfaceTypeDescription2 xIfaceType = xSingletonType.getInterface() as XInterfaceTypeDescription2; if (xIfaceType == null) xIfaceType = resolveInterfaceTypedef( xSingletonType.getInterface()); Type retType = get_type(xIfaceType); // Create the ConstructorInfo for a DeploymentException Type typeDeploymentExc = get_type("unoidl.com.sun.star.uno.DeploymentException", true); Type[] typeCtor = new Type[] { typeof(System.String), typeof(System.Object) }; ConstructorInfo ctorDeploymentException = typeDeploymentExc.GetConstructor(typeCtor); // define method Type[] typeParameters = new Type[] { get_type( "unoidl.com.sun.star.uno.XComponentContext", true) }; MethodBuilder method_builder = type_builder.DefineMethod( "get", (MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Static), retType, typeParameters); // method_builder.SetCustomAttribute(get_service_ctor_method_attribute(ctorDes)); // The first parameter is the XComponentContext, which cannot be // obtained using reflection. // The context is not part of the idl description /* ParameterBuilder param_builder = */ method_builder.DefineParameter( 1, ParameterAttributes.In, "the_context"); ilGen = method_builder.GetILGenerator(); // Define locals // Any, returned by XComponentContext.getValueByName LocalBuilder local_any = ilGen.DeclareLocal(typeof(uno.Any)); // Call XContext.getValueByName ilGen.Emit(OpCodes.Ldarg_0); // build the singleton name: /singleton/unoidl.com.sun.star.XXX ilGen.Emit(OpCodes.Ldstr, "/singletons/" + sSingletonName); MethodInfo methodGetValueByName = get_type("unoidl.com.sun.star.uno.XComponentContext", true).GetMethod("getValueByName"); ilGen.Emit(OpCodes.Callvirt, methodGetValueByName); ilGen.Emit(OpCodes.Stloc_0); // Does the returned Any contain a value? ilGen.Emit(OpCodes.Ldloca_S, local_any); MethodInfo methodHasValue = typeof(uno.Any).GetMethod("hasValue"); ilGen.Emit(OpCodes.Call, methodHasValue); // If not, then throw a DeploymentException Label label_singleton_exists = ilGen.DefineLabel(); ilGen.Emit(OpCodes.Brtrue_S, label_singleton_exists); ilGen.Emit(OpCodes.Ldstr, "Component context fails to supply singleton " + sSingletonName + " of type " + retType.FullName + "."); ilGen.Emit(OpCodes.Ldarg_0); ilGen.Emit(OpCodes.Newobj, ctorDeploymentException); ilGen.Emit(OpCodes.Throw); ilGen.MarkLabel(label_singleton_exists); // Cast the singleton contained in the Any to the expected // interface and return it. ilGen.Emit(OpCodes.Ldloca_S, local_any); ilGen.Emit(OpCodes.Call, typeof(uno.Any).GetProperty("Value").GetGetMethod()); ilGen.Emit(OpCodes.Castclass, retType); ilGen.Emit(OpCodes.Ret); // remove from incomplete singletons map m_incomplete_singletons.Remove(type_builder.FullName); if (Climaker.g_verbose) { Console.WriteLine("> emitting singleton type {0}", type_builder.FullName); } return type_builder.CreateType(); }
Type get_type(XSingletonTypeDescription2 xType) { if (!xType.isInterfaceBased()) return null; string cts_name = to_cts_name(xType.getName()); Type ret_type = get_type(cts_name, false /* no exc */); if (ret_type != null) return ret_type; TypeAttributes attr = (TypeAttributes.Public | TypeAttributes.Sealed | TypeAttributes.BeforeFieldInit | TypeAttributes.AnsiClass); TypeBuilder type_builder = m_module_builder.DefineType(cts_name, attr); // insert to be completed singleton_entry entry = new singleton_entry(); entry.m_xType = xType; entry.m_type_builder = type_builder; m_incomplete_singletons.Add(cts_name, entry); return type_builder; }