示例#1
0
    //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();
    }
示例#2
0
    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;
    }