/// <summary>define the box-Type for the CLS arrayType</summary>
        private void DefineBoxedTypeForCLSArray(TypeBuilder boxBuilder, Type arrayType,
                                                BoxedValueRuntimeTypeGenerator gen)
        {
            IlEmitHelper.GetSingleton().AddSerializableAttribute(boxBuilder);
            // add the field for the boxed value content
            FieldBuilder valField = DefineBoxedField(boxBuilder, arrayType, gen);

            // define getValue method
            DefineGetValue(boxBuilder, valField);
            // define getBoxed type methods:
            DefineGetBoxedType(boxBuilder, valField);
            DefineGetBoxedTypeAttributes(boxBuilder, valField);
            DefineGetFirstNonBoxedType(boxBuilder, arrayType);
            DefineGetFirstNonBoxedTypeName(boxBuilder, arrayType);
            // define the constructors
            DefineEmptyDefaultConstr(boxBuilder);
            // define the constructor which sets the valField directly
            DefineAssignConstr(boxBuilder, valField);
            // define the constructor which transforms a .NET array to the form assignable to the valField, if types are different
            if (!valField.FieldType.Equals(arrayType))
            {
                // need a constructor which transforms instance before assigning
                DefineTransformAndAssignConstrForArray(boxBuilder, valField, arrayType);
            }
        }
Ejemplo n.º 2
0
        private void BeginType()
        {
            // add IdlUnion attribute
            m_builder.SetCustomAttribute(new IdlUnionAttribute().CreateAttributeBuilder());
            IlEmitHelper.GetSingleton().AddSerializableAttribute(m_builder);

            AddTypeField();
            AddInitalizedFieldAndProperty();
            AddStaticConstructor(); // add the static constructor
        }
        /// <summary>define the box-Type for the boxed type other than a CLS array</summary>
        private void DefineBoxedType(TypeBuilder boxBuilder, Type boxedType,
                                     CustomAttributeBuilder[] attrsOnBoxedType)
        {
            IlEmitHelper.GetSingleton().AddSerializableAttribute(boxBuilder);
            // add the field for the boxed value content
            FieldBuilder valField = DefineBoxedField(boxBuilder, boxedType, attrsOnBoxedType);

            // define getValue method
            DefineGetValue(boxBuilder, valField);
            // define getBoxed type methods:
            DefineGetBoxedType(boxBuilder, valField);
            DefineGetBoxedTypeAttributes(boxBuilder, valField);
            Type fullUnboxed = boxedType;

            if ((fullUnboxed.IsArray) && (fullUnboxed.GetElementType().IsSubclassOf(ReflectionHelper.BoxedValueBaseType)))
            {
                // call GetFirstNonBoxed static method on element type
                try {
                    Type unboxedElemType = (Type)fullUnboxed.GetElementType().InvokeMember(
                        BoxedValueBase.GET_FIRST_NONBOXED_TYPE_METHODNAME,
                        BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.NonPublic |
                        BindingFlags.Static | BindingFlags.DeclaredOnly,
                        null, null, new object[0]);
                    Array dummyArray = Array.CreateInstance(unboxedElemType, 0);
                    fullUnboxed = dummyArray.GetType();
                } catch (Exception) {
                    // invalid type found in boxed value creation: " + fullUnboxed
                    throw new INTERNAL(10045, CompletionStatus.Completed_MayBe);
                }
            }
            else if (fullUnboxed.IsSubclassOf(ReflectionHelper.BoxedValueBaseType))
            {
                // call GetFirstNonBoxed static method on type
                try {
                    fullUnboxed = (Type)fullUnboxed.InvokeMember(
                        BoxedValueBase.GET_FIRST_NONBOXED_TYPE_METHODNAME,
                        BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.NonPublic |
                        BindingFlags.Static | BindingFlags.DeclaredOnly,
                        null, null, new object[0]);
                } catch (Exception) {
                    // invalid type found: fullUnboxed,
                    // static method missing or not callable:
                    // BoxedValueBase.GET_FIRST_NONBOXED_TYPE_METHODNAME
                    throw new INTERNAL(10044, CompletionStatus.Completed_MayBe);
                }
            }

            if ((fullUnboxed.IsArray) && (fullUnboxed.GetElementType().IsArray))
            {
                // add a constructor, which takes a CLS array (with an element type which is also an array) and creates the boxed value type for the instance
                // for arrays with an element type, which is not an array, such a constructor already exists
                DefineTransformAndAssignConstrForArray(boxBuilder, valField, fullUnboxed);
            }

            if ((boxedType.IsArray) && (!boxedType.GetElementType().IsArray) &&
                (boxedType.GetElementType().IsSubclassOf(ReflectionHelper.BoxedValueBaseType)))
            {
                Type boxedElemType;
                try {
                    // get the type boxed in the element
                    boxedElemType = (Type)boxedType.GetElementType().InvokeMember(
                        BoxedValueBase.GET_BOXED_TYPE_METHOD_NAME,
                        BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.NonPublic |
                        BindingFlags.Static | BindingFlags.DeclaredOnly,
                        null, null, new object[0]);
                } catch (Exception) {
                    // invalid type found: boxedType.GetElementType(),
                    // static method missing or not callable:
                    // BoxedValueBase.GET_BOXED_TYPE_METHOD_NAME
                    throw new INTERNAL(10044, CompletionStatus.Completed_MayBe);
                }

                if (!boxedElemType.IsArray)
                {
                    // The boxed type which should be defined, has type of the following form boxed:
                    // a sequence of BoxedValues, but these boxed values do not box arrays itself
                    // for this boxed type an additional transform constructor is needed, which boxes the elements
                    // of the sequence
                    Array boxedInnerArray = Array.CreateInstance(boxedElemType, 0);
                    DefineTransformAndAssignConstrForArray(boxBuilder, valField, boxedInnerArray.GetType());
                }
            }

            if ((!boxedType.IsArray) && (boxedType.IsSubclassOf(ReflectionHelper.BoxedValueBaseType)))
            {
                // The boxed value type boxes another boxed value type --> need a transform constructor,
                // which takes an unboxed value and boxes it, before assigning it to the field
                // TODO: implement this
                throw new NO_IMPLEMENT(12345, CompletionStatus.Completed_MayBe);
            }

            DefineGetFirstNonBoxedType(boxBuilder, fullUnboxed);
            DefineGetFirstNonBoxedTypeName(boxBuilder, fullUnboxed);
            // define the constructors
            DefineEmptyDefaultConstr(boxBuilder);
            // define the constructor which sets the valField directly
            DefineAssignConstr(boxBuilder, valField);
        }