/// <summary> /// specify a special mapping, e.g. CLS ArrayList <=> java.util.ArrayList. /// </summary> /// <param name="clsType">the native cls type, e.g. ArrayList</param> /// <param name="idlType">the idl type (mapped from idl to CLS) used to describe serialisation / deserialisation, e.g. java.util.ArrayListImpl</param> /// <param name="mapper">the mapper, knowing how to map instances of CLS ArrayList to java.util.ArrayListImpl and in the other direction</param> public void AddMapping(Type clsType, Type idlType, ICustomMapper mapper) { // check that idlType implements IIdlEntity: if (!(ReflectionHelper.IIdlEntityType.IsAssignableFrom(idlType))) { throw new Exception("illegal type for custom mapping encountered: " + idlType.FullName); } // be aware: mapping is not bijektive, because of impl classes; however for an idl type only one // cls type is allowed if (m_mappingsIdl.ContainsKey(idlType) && (!((CustomMappingDesc)m_mappingsIdl[idlType]).ClsType.Equals(clsType))) { throw new Exception("mapping constraint violated, tried to insert another cls type " + clsType + "mapped to the idl type " + idlType); } CustomMappingDesc desc = new CustomMappingDesc(clsType, idlType, mapper); m_mappingsCls[clsType] = desc; m_mappingsIdl[idlType] = desc; // check for impl class attribute, if present: add impl class here too object[] implAttr = idlType.GetCustomAttributes(ReflectionHelper.ImplClassAttributeType, false); if ((implAttr != null) && (implAttr.Length > 0)) { ImplClassAttribute implCl = (ImplClassAttribute)implAttr[0]; // get the type Type implIdlType = Repository.GetValueTypeImplClass(implCl.ImplClass); if (implIdlType != null) // if impl type not found, (test needed e.g. when called from CLSToIDLGen) { CustomMappingDesc descImpl = new CustomMappingDesc(clsType, implIdlType, mapper); m_mappingsIdl[implIdlType] = descImpl; } } }
/// <summary> /// takes an instance deserialised from a cdr stream and maps it to the instance /// used in .NET. The mapped instance must be assignable to formalSig. /// </summary> /// <remarks> /// Custom mapping must be present; otherwise an exception is thrown. /// </remarks> public object CreateClsForIdlInstance(object idlInstance, Type formalSig) { // for subtype of idl formal support, get acutal mapping CustomMappingDesc actualMapping = GetMappingForIdl(idlInstance.GetType()); if (actualMapping == null) { throw new BAD_PARAM(12309, CompletionStatus.Completed_MayBe); } ICustomMapper mapper = actualMapping.Mapper; object result = mapper.CreateClsForIdlInstance(idlInstance); // check, if mapped instance is assignable to formal in CLS signature -> otherwise will not work. if (!formalSig.IsAssignableFrom(result.GetType())) { throw new BAD_PARAM(12311, CompletionStatus.Completed_MayBe); } return(result); }
/// <summary> /// takes a .NET instance and maps it to the instance, which should be serialised into /// the CDR stream. The mapped instance must be assignable to the formal type specified in idl. /// </summary> /// <remarks> /// Custom mapping must be present; otherwise an exception is thrown. /// </remarks> public object CreateIdlForClsInstance(object clsInstance, Type formal) { // for subtypes support (subtypes of formal before cls to idl mapping; new formal is idl formal) CustomMappingDesc actualMapping = GetMappingForCls(clsInstance.GetType()); if (actualMapping == null) { throw new BAD_PARAM(12308, CompletionStatus.Completed_MayBe); } ICustomMapper mapper = actualMapping.Mapper; object actual = mapper.CreateIdlForClsInstance(clsInstance); // check, if mapped is instance is assignable to formal -> otherwise will not work on other side ... if (!formal.IsAssignableFrom(actual.GetType())) { throw new BAD_PARAM(12310, CompletionStatus.Completed_MayBe); } return(actual); }
/// <summary> /// specify a special mapping, e.g. CLS ArrayList <=> java.util.ArrayList. /// </summary> /// <param name="clsType">the native cls type, e.g. ArrayList</param> /// <param name="idlType">the idl type (mapped from idl to CLS) used to describe serialisation / deserialisation, e.g. java.util.ArrayListImpl</param> /// <param name="mapper">the mapper, knowing how to map instances of CLS ArrayList to java.util.ArrayListImpl and in the other direction</param> public void AddMapping(Type clsType, Type idlType, ICustomMapper mapper) { // check that idlType implements IIdlEntity: if (!(ReflectionHelper.IIdlEntityType.IsAssignableFrom(idlType))) { throw new Exception("illegal type for custom mapping encountered: " + idlType.FullName); } // be aware: mapping is not bijektive, because of impl classes; however for an idl type only one // cls type is allowed if (m_mappingsIdl.ContainsKey(idlType) && (!((CustomMappingDesc)m_mappingsIdl[idlType]).ClsType.Equals(clsType))) { throw new Exception("mapping constraint violated, tried to insert another cls type " + clsType + "mapped to the idl type " + idlType); } CustomMappingDesc desc = new CustomMappingDesc(clsType, idlType, mapper); m_mappingsCls[clsType] = desc; m_mappingsIdl[idlType] = desc; // check for impl class attribute, if present: add impl class here too object[] implAttr = idlType.GetCustomAttributes(ReflectionHelper.ImplClassAttributeType, false); if ((implAttr != null) && (implAttr.Length > 0)) { ImplClassAttribute implCl = (ImplClassAttribute) implAttr[0]; // get the type Type implIdlType = Repository.GetValueTypeImplClass(implCl.ImplClass); if (implIdlType != null) { // if impl type not found, (test needed e.g. when called from CLSToIDLGen) CustomMappingDesc descImpl = new CustomMappingDesc(clsType, implIdlType, mapper); m_mappingsIdl[implIdlType] = descImpl; } } }
/// <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"); }