/// <summary> /// call the appropriate mapping action for a CLSType array /// </summary> private object CallActionForDNArray(ref Type clsType, ref AttributeExtCollection modifiedAttributes, AttributeExtCollection allAttributes, MappingAction action) { // distinguish the different cases here Attribute idlMappingAttr = modifiedAttributes.GetHighestOrderAttribute(); if (idlMappingAttr is IdlSequenceAttribute) { modifiedAttributes = modifiedAttributes.RemoveAttribute(idlMappingAttr); int bound = (int) ((IdlSequenceAttribute)idlMappingAttr).Bound; return action.MapToIdlSequence(clsType, bound, allAttributes, modifiedAttributes); } else if (idlMappingAttr is IdlArrayAttribute) { IdlArrayAttribute arrayAttr = (IdlArrayAttribute)idlMappingAttr; modifiedAttributes = modifiedAttributes.RemoveAttribute(idlMappingAttr); int[] dimensions = DetermineIdlArrayDimensions(clsType, arrayAttr, ref modifiedAttributes); return action.MapToIdlArray(clsType, dimensions, allAttributes, modifiedAttributes); } else { Type boxed = GetBoxedArrayType(clsType); Type needsBoxingFrom = clsType; clsType = boxed; // transform return action.MapToIdlBoxedValueType(boxed, needsBoxingFrom); } }
/// <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"); }