예제 #1
0
 /// <summary>determines the mapping for the case, where clsType is a CLS-interface</summary>
 private object CallActionForDNInterface(ref Type clsType, MappingAction action) {
     // distinguish the different cases here
     object[] attrs = clsType.GetCustomAttributes(s_interfaceTypeAttrType, true);
     if (attrs.Length > 1) { 
         // only one InterfaceTypeAttribute for an interface allowed
         throw new INTERNAL(18811, CompletionStatus.Completed_MayBe);
     }
 
     InterfaceTypeAttribute interfaceAttr = null;
     if (attrs.Length > 0) { 
         interfaceAttr = (InterfaceTypeAttribute) attrs[0]; 
     }
     if ((interfaceAttr == null) || (interfaceAttr.IdlType.Equals(IdlTypeInterface.AbstractInterface))) {
         return action.MapToIdlAbstractInterface(clsType);
     } else if (interfaceAttr.IdlType.Equals(IdlTypeInterface.ConcreteInterface)) {
         return action.MapToIdlConcreteInterface(clsType);
     } else if (interfaceAttr.IdlType.Equals(IdlTypeInterface.AbstractValueType)) {
         return action.MapToIdlAbstractValueType(clsType);
     } else if (interfaceAttr.IdlType.Equals(IdlTypeInterface.LocalInterface)) {
         return action.MapToIdlLocalInterface(clsType);
     } else  {
         // ttributte IntrerfaceTypeAttribute had an unknown value for IDLType: interfaceAttr.IdlType
         throw new MARSHAL(18809, CompletionStatus.Completed_MayBe);
     }
 }
예제 #2
0
        /// <summary>uses MappingAction action while mapping a CLS-type to an IDL-type</summary>
        /// <param name="clsType">the type to map. The mapper can decide to transform the type during the mapping, the result of the transformation is returned. Transformation occurs, for example because of attributes</param>
        /// <param name="action">the action to take for the determined mapping</param>
        /// <param name="attributes">the attributes on the param, field, return value; a new collection without the considered attributes is returned</param>
        /// <param name="usedCustomMapping">the custom mapping used if any; otherwise null</param>
        public object MapClsTypeWithTransform(ref Type clsType, ref AttributeExtCollection attributes, MappingAction action,
                                              out CustomMappingDesc usedCustomMapping) {
                                              
            TypeCodeCreater.TypecodeForTypeKey key = new TypeCodeCreater.TypecodeForTypeKey(clsType, attributes);
            MapType mapType = MapType.Unknown;
            
            lock(mapTypes) {
                if(!mapTypes.TryGetValue(key, out mapType))
                    mapType = MapType.Unknown;
            }
            // handle out, ref types correctly: no other action needs to be taken than for in-types
            usedCustomMapping = null;
            AttributeExtCollection originalAttributes = attributes; // used to save reference to the passed in attributes
            if (clsType.IsByRef) {
                clsType = clsType.GetElementType(); 
            }
            
            // check for plugged special mappings, e.g. CLS ArrayList -> java.util.ArrayList
            CustomMapperRegistry cReg = CustomMapperRegistry.GetSingleton();
            if (cReg.IsCustomMappingPresentForCls(clsType)) {
                usedCustomMapping = cReg.GetMappingForCls(clsType);
                clsType = usedCustomMapping.IdlType;
            }

            // check some standard cases
            Attribute boxedValAttr;
            attributes = originalAttributes.RemoveAttributeOfType(s_boxedValAttrType, out boxedValAttr);
            
            if(mapType == MapType.Unknown)
            {
                if (boxedValAttr != null) { 
                    // load the boxed value-type for this attribute
                    Type boxed = GetBoxedValueType((BoxedValueAttribute)boxedValAttr);
                    if (boxed == null) { 
                        Trace.WriteLine("boxed type not found for boxed value attribute"); 
                        mapType = MapType.BoxedValueNotFound;
                    } else {
                        Type needsBoxingFrom = clsType;
                        clsType = boxed; // transformation
                        mapType = MapType.BoxedValue;
                    }
                } else if (IsInterface(clsType) && !(clsType.Equals(ReflectionHelper.CorbaTypeCodeType))) {
                    mapType = MapType.Interface;
                } else if (IsMarshalByRef(clsType)) {
                    mapType = MapType.MarshalByRef;
                } else if (IsMappablePrimitiveType(clsType)) {
                    mapType = MapType.Primitive;
                } else if (IsEnum(clsType)) { 
                    if (HasEnumFlagsAttributes(clsType)) {
                        mapType = MapType.Flags;
                    } else {
                        // enums with more than Int32.MaxValue elements can't be mapped to idl.
                        // but not possibly to check this, because in .NET 1.0, no support for Array.LongLength.
                        mapType = MapType.Enum;
                    }
                } else if (IsArray(clsType)) { 
                    mapType = MapType.Array;
                } else if (clsType.IsSubclassOf(ReflectionHelper.BoxedValueBaseType)) {
                    // a boxed value type, which needs not to be boxed/unboxed but should be handled like a normal value type
                    mapType = MapType.BoxedValue2;
                } else if (clsType.IsSubclassOf(s_exceptType) || clsType.Equals(s_exceptType)) {
                    mapType = MapType.Exception;
                } else if (IsMarshalledAsStruct(clsType)) {
                     mapType = MapType.Struct;
                } else if (IsMarshalledAsUnion(clsType)) {
                    mapType = MapType.Union;
                } else if (clsType.Equals(ReflectionHelper.ObjectType)) {
                    mapType = MapType.Object;
                } else if (clsType.Equals(s_anyType)) {
                    mapType = MapType.Any;
                } else if (clsType.Equals(ReflectionHelper.TypeType) || clsType.IsSubclassOf(ReflectionHelper.TypeType)) {
                    mapType = MapType.TypeDesc;
                } else if (clsType.Equals(s_corbaTypeCodeImplType) || clsType.IsSubclassOf(s_corbaTypeCodeImplType) ||
                           clsType.Equals(ReflectionHelper.CorbaTypeCodeType)) {
                    mapType = MapType.TypeCode;
                } else if (!UnmappableType(clsType)) {
                    if (IsValueTypeConcrete(clsType)) {
                        mapType = MapType.ConcreteValue;
                    } else {
                        // other types are mapped to an abstract value type
                        mapType = MapType.AbstractValue;
                    }
                } else {
                    // not mappable: clsType
                    mapType = MapType.Unmappable;
                }
                
                lock(mapTypes)
                    mapTypes[key] = mapType;
            }
            
            switch(mapType)
            {
                case MapType.BoxedValueNotFound:
                    Trace.WriteLine("boxed type not found for boxed value attribute"); 
                    throw new NO_IMPLEMENT(10001, CompletionStatus.Completed_MayBe);
                case MapType.BoxedValue:
                    Type boxed = GetBoxedValueType((BoxedValueAttribute)boxedValAttr);
                    Type needsBoxingFrom = clsType;
                    clsType = boxed; // transformation
                    return action.MapToIdlBoxedValueType(boxed, needsBoxingFrom);
                case MapType.Interface:
                    return CallActionForDNInterface(ref clsType, action);
                case MapType.MarshalByRef:
                    return action.MapToIdlConcreteInterface(clsType);
                case MapType.Primitive:
                    return CallActionForDNPrimitveType(ref clsType, ref attributes, action);
                case MapType.Flags:
                    return action.MapToIdlFlagsEquivalent(clsType);
                case MapType.Enum:
                    // enums with more than Int32.MaxValue elements can't be mapped to idl.
                    // but not possibly to check this, because in .NET 1.0, no support for Array.LongLength.
                    return action.MapToIdlEnum(clsType);
                case MapType.Array:
                    return CallActionForDNArray(ref clsType, ref attributes, originalAttributes, action);
                case MapType.BoxedValue2:
                    // a boxed value type, which needs not to be boxed/unboxed but should be handled like a normal value type
                    return action.MapToIdlBoxedValueType(clsType, null);
                case MapType.Exception:
                    return action.MapException(clsType);
                case MapType.Struct:
                     return action.MapToIdlStruct(clsType);
                case MapType.Union:
                    return action.MapToIdlUnion(clsType);
                case MapType.Object:
                    return CallActionForDNObject(ref clsType, ref attributes, action);
                case MapType.Any:
                    return action.MapToIdlAny(clsType);
                case MapType.TypeDesc:
                    return action.MapToTypeDesc(clsType);
                case MapType.TypeCode:
                    return action.MapToTypeCode(clsType);
                case MapType.ConcreteValue:
                    return action.MapToIdlConcreateValueType(clsType);
                case MapType.AbstractValue:
                    // other types are mapped to an abstract value type
                    return action.MapToIdlAbstractValueType(clsType);                   
            }
            // not mappable: clsType
            throw new BAD_PARAM(18800, CompletionStatus.Completed_MayBe, "The type " + clsType.AssemblyQualifiedName +
                               " is not mappable to idl");
        }