//Examples of generated code // public static XWeak constructor1(XComponentContext ctx) // { // XMultiComponentFactory factory = ctx.getServiceManager(); // if (factory == null) // throw new com.sun.star.uno.DeploymentException("bla", null); // return (XWeak) factory.createInstanceWithContext("service_specifier", ctx); // } // public static XWeak constructor2(XComponentContext ctx, int a, int b) // { // XMultiComponentFactory factory = ctx.getServiceManager(); // if (factory == null) // throw new com.sun.star.uno.DeploymentException("bla", null); // Any a1; // a1 = new Any( typeof(int), a); // Any a2; // a2 = new Any( typeof(int), b); // Any[] arAny = new Any[2]; // arAny[0] = a1; // arAny[1] = a2; // return (XWeak) factory.createInstanceWithArgumentsAndContext("service_specifier", arAny, ctx); // } // public static XWeak constructor3(XComponentContext ctx, params Any[] c) // { // XMultiComponentFactory factory = ctx.getServiceManager(); // if (factory == null) // throw new com.sun.star.uno.DeploymentException("bla", null); // return (XWeak) factory.createInstanceWithArgumentsAndContext("service_specifier", c, ctx); // } Type complete_service_type(service_entry entry) { TypeBuilder type_builder = entry.m_type_builder; XServiceTypeDescription2 xServiceType = entry.m_xType; // Create the private default constructor ConstructorBuilder ctor_builder = type_builder.DefineConstructor( (MethodAttributes.Private | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName), CallingConventions.Standard, null); ILGenerator code = ctor_builder.GetILGenerator(); code.Emit(OpCodes.Ldarg_0); // push this code.Emit(OpCodes.Call, type_builder.BaseType.GetConstructor(new Type[0])); code.Emit(OpCodes.Ret); // Create the service constructors. // optain the interface which makes up this service, it is the // return type of the constructor functions XInterfaceTypeDescription2 xIfaceType = xServiceType.getInterface() as XInterfaceTypeDescription2; if (xIfaceType == null) xIfaceType = resolveInterfaceTypedef(xServiceType.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); XServiceConstructorDescription[] ctors = xServiceType.getConstructors(); Type type_uno_exception = get_type("unoidl.com.sun.star.uno.Exception", true); for (int i = ctors.Length - 1; i >= 0; --i) { bool bParameterArray = false; Type typeAny = typeof(uno.Any); XServiceConstructorDescription ctorDes = ctors[i]; // obtain the parameter types XParameter[] xParams = ctorDes.getParameters(); Type[] typeParameters = new Type[xParams.Length + 1]; typeParameters[0] = get_type("unoidl.com.sun.star.uno.XComponentContext", true); for (int iparam = 0; iparam != xParams.Length; ++iparam) { if (xParams[iparam].isRestParameter()) typeParameters[iparam + 1] = typeof(uno.Any[]); else typeParameters[iparam + 1] = get_type(xParams[iparam].getType()); } // define method string ctorName; if (ctorDes.isDefaultConstructor()) ctorName = "create"; else ctorName = ctorDes.getName(); MethodBuilder method_builder = type_builder.DefineMethod( ctorName, (MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Static), retType, typeParameters); // define UNO exception attribute (exceptions) CustomAttributeBuilder attrBuilder = get_service_exception_attribute(ctorDes); if (attrBuilder != null) method_builder.SetCustomAttribute(attrBuilder); // define parameter attributes (paramarray), names etc. // The first parameter is the XComponentContext, which cannot be // obtained from reflection. // The context is not part of the idl description /* ParameterBuilder param_builder = */ method_builder.DefineParameter( 1, ParameterAttributes.In, "the_context"); ParameterBuilder[] parameterBuilders = new ParameterBuilder[xParams.Length]; for (int iparam = 0; iparam != xParams.Length + 1; ++iparam) { parameterBuilders[iparam] = method_builder.DefineParameter( iparam + 2, ParameterAttributes.In, xParams[iparam].getName()); if (xParams[iparam].isRestParameter()) { bParameterArray = true; // set the ParameterArrayAttribute ConstructorInfo ctor_info = typeof(System.ParamArrayAttribute).GetConstructor( new Type[0]); CustomAttributeBuilder attr_builder = new CustomAttributeBuilder(ctor_info, new object[0]); parameterBuilders[iparam].SetCustomAttribute(attr_builder); break; } } ILGenerator ilGen = method_builder.GetILGenerator(); // Define locals // XMultiComponentFactory LocalBuilder local_factory = ilGen.DeclareLocal( get_type("unoidl.com.sun.star.lang.XMultiComponentFactory", true)); // The return type LocalBuilder local_return_val = ilGen.DeclareLocal(retType); // Obtain the XMultiComponentFactory and throw an exception if we // do not get one ilGen.Emit(OpCodes.Ldarg_0); MethodInfo methodGetServiceManager = get_type( "unoidl.com.sun.star.uno.XComponentContext", true) .GetMethod("getServiceManager"); ilGen.Emit(OpCodes.Callvirt, methodGetServiceManager); ilGen.Emit(OpCodes.Stloc, local_factory); ilGen.Emit(OpCodes.Ldloc, local_factory); Label label1 = ilGen.DefineLabel(); ilGen.Emit(OpCodes.Brtrue, label1); ilGen.Emit(OpCodes.Ldstr, String.Format("The service unoidl.{0} could not be created. The context failed to supply the service manager.", xServiceType.getName())); ilGen.Emit(OpCodes.Ldarg_0); ilGen.Emit(OpCodes.Newobj, ctorDeploymentException); ilGen.Emit(OpCodes.Throw); ilGen.MarkLabel(label1); // We create a try/catch around the createInstanceWithContext, // etc. functions // There are 3 cases // 1. function do not specify exceptions. Then // RuntimeExceptions are retrhown and other exceptions // produce a DeploymentException. // 2. function specify Exception. Then all exceptions fly // through // 3. function specifies exceptions but no Exception. Then // these are rethrown and other exceptions, except // RuntimeException, produce a deployment exception. // In case there are no parameters we call // XMultiComponentFactory.createInstanceWithContext ArrayList exceptionTypes = get_service_ctor_method_exceptions_reduced( ctorDes.getExceptions()); if (! exceptionTypes.Contains(type_uno_exception)) { ilGen.BeginExceptionBlock(); } if (xParams.Length == 0) { ilGen.Emit(OpCodes.Ldloc, local_factory); ilGen.Emit(OpCodes.Ldstr, to_cts_name(xServiceType.getName())); ilGen.Emit(OpCodes.Ldarg_0); MethodInfo methodCIWAAC = local_factory.LocalType.GetMethod( "createInstanceWithArgumentsAndContext"); ilGen.Emit(OpCodes.Callvirt, methodCIWAAC); } else if (bParameterArray) { // Service constructor with parameter array ilGen.Emit(OpCodes.Ldloc, local_factory); ilGen.Emit(OpCodes.Ldstr, to_cts_name(xServiceType.getName())); ilGen.Emit(OpCodes.Ldarg_1); ilGen.Emit(OpCodes.Ldarg_0); MethodInfo methodCIWAAC = local_factory.LocalType.GetMethod( "createInstanceWithArgumentsAndContext"); ilGen.Emit(OpCodes.Callvirt, methodCIWAAC); } else { // Any param1, Any param2, etc. // For each parameter, except the component context, and // the parameter array an Any is created. LocalBuilder[] localAnys = new LocalBuilder[xParams.Length]; for (int iparam = 0; iparam < xParams.Length; ++iparam) { localAnys[iparam] = ilGen.DeclareLocal(typeAny); } // Any[]. This array is filled with the created Anys // which contain the parameters and the values // contained in the parameter array LocalBuilder local_anyParams = ilGen.DeclareLocal(typeof(uno.Any[])); // Create the Any for every argument, except for the // parameter array. localAnys contains the LocalBuilder for // all these parameters. We call the ctor Any(Type, Object) Type[] typesCtorAny = { typeof(System.Type), typeof(System.Object) }; ConstructorInfo ctorAny = typeAny.GetConstructor(typesCtorAny); for (int j = 0; j < localAnys.Length; ++j) { ilGen.Emit(OpCodes.Ldloca, localAnys[j]); ilGen.Emit(OpCodes.Ldtoken, typeParameters[j+1]); Type[] typeParams = { typeof(System.RuntimeTypeHandle) }; ilGen.Emit(OpCodes.Call, typeof(System.Type).GetMethod( "GetTypeFromHandle", typeParams)); ilGen.Emit(OpCodes.Ldarg, j + 1); // if the parameter is a value type then we need // to box it, because the Any ctor takes an Object if (typeParameters[j+1].IsValueType) ilGen.Emit(OpCodes.Box, typeParameters[j+1]); ilGen.Emit(OpCodes.Call, ctorAny); } // Create the Any[] that is passed to the // createInstanceWithContext[AndArguments] function ilGen.Emit(OpCodes.Ldc_I4, localAnys.Length); ilGen.Emit(OpCodes.Newarr, typeAny); ilGen.Emit(OpCodes.Stloc, local_anyParams); // Assign all anys created from the parameters array // to the Any[] for (int j = 0; j < localAnys.Length; ++j) { ilGen.Emit(OpCodes.Ldloc, local_anyParams); ilGen.Emit(OpCodes.Ldc_I4, j); ilGen.Emit(OpCodes.Ldelema, typeAny); ilGen.Emit(OpCodes.Ldloc, localAnys[j]); ilGen.Emit(OpCodes.Stobj, typeAny); } // call createInstanceWithContextAndArguments ilGen.Emit(OpCodes.Ldloc, local_factory); ilGen.Emit(OpCodes.Ldstr, to_cts_name(xServiceType.getName())); ilGen.Emit(OpCodes.Ldloc, local_anyParams); ilGen.Emit(OpCodes.Ldarg_0); MethodInfo methodCIWAAC = local_factory.LocalType.GetMethod( "createInstanceWithArgumentsAndContext"); ilGen.Emit(OpCodes.Callvirt, methodCIWAAC); } // cast the object returned by the functions // createInstanceWithContext or // createInstanceWithArgumentsAndContext to the interface type ilGen.Emit(OpCodes.Castclass, retType); ilGen.Emit(OpCodes.Stloc, local_return_val); // catch exceptions thrown by createInstanceWithArgumentsAndContext // and createInstanceWithContext if (!exceptionTypes.Contains(type_uno_exception)) { // catch (unoidl.com.sun.star.uno.RuntimeException) {throw;} ilGen.BeginCatchBlock( get_type( "unoidl.com.sun.star.uno.RuntimeException", true)); ilGen.Emit(OpCodes.Pop); ilGen.Emit(OpCodes.Rethrow); // catch and rethrow all other defined Exceptions foreach (Type excType in exceptionTypes) { if (excType.IsInstanceOfType( get_type( "unoidl.com.sun.star.uno.RuntimeException", true))) { // we have a catch for RuntimeException already defined continue; } // catch Exception and rethrow ilGen.BeginCatchBlock(excType); ilGen.Emit(OpCodes.Pop); ilGen.Emit(OpCodes.Rethrow); } // catch (unoidl.com.sun.star.uno.Exception) // { throw DeploymentException... } ilGen.BeginCatchBlock(type_uno_exception); // define the local variable that keeps the exception LocalBuilder local_exception = ilGen.DeclareLocal( type_uno_exception); // Store the exception ilGen.Emit(OpCodes.Stloc, local_exception); // prepare the construction of the exception ilGen.Emit(OpCodes.Ldstr, "The context (com.sun.star.uno.XComponentContext)" + "failed to supply the service " + to_cts_name(xServiceType.getName()) + ": "); // add to the string the Exception.Message ilGen.Emit(OpCodes.Ldloc, local_exception); ilGen.Emit(OpCodes.Callvirt, type_uno_exception.GetProperty("Message") .GetGetMethod()); Type[] concatParams = new Type[] { typeof(System.String), typeof(System.String) }; ilGen.Emit(OpCodes.Call, typeof(System.String).GetMethod("Concat", concatParams)); // load context argument ilGen.Emit(OpCodes.Ldarg_0); ilGen.Emit(OpCodes.Newobj, ctorDeploymentException); ilGen.Emit(OpCodes.Throw); // Exception(typeDeploymentExc); ilGen.EndExceptionBlock(); } // Check if the service instance was create and throw an // exception if not. Label label_service_created = ilGen.DefineLabel(); ilGen.Emit(OpCodes.Ldloc, local_return_val); ilGen.Emit(OpCodes.Brtrue_S, label_service_created); ilGen.Emit(OpCodes.Ldstr, "The context (com.sun.star.uno.XComponentContext)" + "failed to supply the service unoidl." + to_cts_name(xServiceType.getName()) + "."); ilGen.Emit(OpCodes.Ldarg_0); ilGen.Emit(OpCodes.Newobj, ctorDeploymentException); ilGen.Emit(OpCodes.Throw); // Exception(typeDeploymentExc); ilGen.MarkLabel(label_service_created); ilGen.Emit(OpCodes.Ldloc, local_return_val); ilGen.Emit(OpCodes.Ret); } // remove from incomplete types map m_incomplete_services.Remove(type_builder.FullName); if (Climaker.g_verbose) { Console.WriteLine("> emitting service type {0}", type_builder.FullName); } return type_builder.CreateType(); }
Type get_type(XServiceTypeDescription2 xType) { if (!xType.isSingleInterfaceBased()) 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 service_entry entry = new service_entry(); entry.m_xType = xType; entry.m_type_builder = type_builder; m_incomplete_services.Add(cts_name, entry); return type_builder; }