/// <summary> /// Creates a convertible from a descriptor. Only works if a creator function was /// registered (see RegisterCreator). /// </summary> public Convertible FromDescriptor(string descriptor) { List <Func <Convertible> > creators; if (!m_creatorsMap.TryGetValue(descriptor, out creators)) { return(null); } var func = creators.First(); Convertible conv = func(); return(conv); }
/// <summary> /// Returns a matching raw convertible for a convertible. Only works if a raw convertible /// was registered (see RegisterRaw). /// </summary> public Convertible FindMatchingRaw(Convertible c) { var desc = c.Descriptor; List <Func <Convertible> > creators; if (!m_rawConvertiblesMap.TryGetValue(desc, out creators)) { return(null); } var func = creators.First(); Convertible conv = func(); return(conv); }
/// <summary> /// Returns a matching raw convertible by also taking a preferred target into account. /// Only works if a raw convertible was registered (see RegisterRaw). /// </summary> public Convertible FindMatchingRaw(Convertible conv, string preferrableTargetDescriptor) { List <Func <Convertible> > creators; if (!m_rawConvertiblesMap.TryGetValue(conv.Descriptor, out creators)) { return(null); } var c = (from func in creators let source = func() let distance = m_routingMap[source.Descriptor][preferrableTargetDescriptor].Distance orderby distance ascending select source).First(); return(c); }
/// <summary> /// Returns a matching file convertible given a file name. /// Only works if a convertible was registered for the file extension (see RegisterExtension). /// </summary> public Convertible FindConvertibleByFileName(string fileName) { var fileExt = Path.GetExtension(fileName).ToLower(); List <Func <string, Convertible> > creators; if (!m_fileExtensionsMap.TryGetValue(fileExt, out creators)) { throw new ArgumentException("no convertible available for this file extension", fileExt); } foreach (var func in creators) { Convertible conv = func(fileName); if (AreAllResourcesAvailable(conv.Descriptor)) { return(conv); } } throw new ArgumentException("could not find a creator for this file extension", fileExt); }
/// <summary> /// Direct conversion between two convertibles. /// </summary> private void DirectConvert(Convertible source, Convertible target) { if (source.Data == null) { throw new ArgumentNullException(); } var conversion = new Pair <string>(source.Descriptor, target.Descriptor); Action <Convertible, Convertible> procedure; if (m_actionMap.TryGetValue(conversion, out procedure)) { procedure(source, target); } else if (source.Descriptor == target.Descriptor) { target.Data = source.Data; } else { throw new ConversionNotPossibleException(source.Descriptor, target.Descriptor, "convert failed"); } }
public void Code(ref object obj) { var typeName = m_reader.ReadString(); TypeInfo newTypeInfo = null; TypeInfo typeInfo; if (TryGetTypeInfo(typeName, out typeInfo)) { if (typeInfo.Type == typeof(TypeCoder.Null)) { if ((typeInfo.Options & TypeInfo.Option.Active) != 0) { obj = null; return; } else { throw new Exception("cannot decode null object " + "- change by configuring coder with " + "\"coder.Add(TypeCoder.Default.Null);\""); } } if (typeInfo.Type == typeof(TypeCoder.Reference)) { if ((typeInfo.Options & TypeInfo.Option.Active) != 0) { if (CoderVersion < 5) { obj = UseRef(m_reader.ReadInt32()); } else { obj = UseRef(m_reader.ReadGuid()); } return; } else { throw new Exception( "cannot decode multiply referenced object " + "- change by configuring coder with " + "\"coder.Add(TypeCoder.Default.Reference);\""); } } } else { typeInfo = new TypeInfo(typeName, Type.GetType(typeName), TypeInfo.Option.Size | TypeInfo.Option.Version); if ((m_debugMode & CoderDebugMode.ReportQualifiedNames) != 0) { Report.Line("qualified name \"{0}\"", typeName); } } if ((typeInfo.Options & TypeInfo.Option.Version) != 0) { m_versionStack.Push(m_version); m_version = m_reader.ReadInt32(); if (m_version < typeInfo.Version) { TypeInfo oldTypeInfo; if (typeInfo.VersionMap.TryGetValue(m_version, out oldTypeInfo)) { newTypeInfo = typeInfo; typeInfo = oldTypeInfo; } } } long end = 0; if ((typeInfo.Options & TypeInfo.Option.Size) != 0) { end = m_reader.ReadInt64() + m_reader.BaseStream.Position; } if (typeInfo.Type != null) { if (!TypeCoder.ReadPrimitive(this, typeInfo.Type, ref obj)) { if ((typeInfo.Options & TypeInfo.Option.Ignore) != 0) { m_reader.BaseStream.Position = end; obj = null; } else { var codedVersion = m_version; m_typeInfoStack.Push(typeInfo); if (typeInfo.Creator != null) { obj = typeInfo.Creator(); } else { obj = FastObjectFactory.ObjectFactory(typeInfo.Type)(); } if ((m_debugMode & CoderDebugMode.ReportObjects) != 0) { Report.Line("{0,-34} 0x{1:x}", typeName, obj.GetHashCode()); } if (m_doRefs) { AddRef(obj); } #region code fields based on supported interface var fcobj = obj as IFieldCodeable; if (fcobj != null) { CodeFields(typeInfo.Type, codedVersion, fcobj); if (typeInfo.ProxyType != null) { obj = typeInfo.Proxy2ObjectFun(fcobj); } else { var tmobj = obj as ITypedMap; if (tmobj != null) { CodeFields(typeInfo.Type, tmobj); } } if ((typeInfo.Options & TypeInfo.Option.Size) != 0) { m_reader.BaseStream.Position = end; } } else { if ((typeInfo.Options & TypeInfo.Option.Size) != 0) { m_reader.BaseStream.Position = end; Report.Warn( "skipping object of uncodeable type \"{0}\"", typeName); obj = null; } else { throw new Exception( "cannot skip uncodeable object of type \"" + typeName + '"'); } } var aobj = obj as IAwakeable; if (aobj != null) { aobj.Awake(codedVersion); // codedVersion } #endregion m_typeInfoStack.Pop(); } } } else { if ((typeInfo.Options & TypeInfo.Option.Size) != 0) { m_reader.BaseStream.Position = end; Report.Warn("skipping object of unknown type " + typeName); obj = null; } else { throw new Exception( "cannot skip object of unknown type \"" + typeName + '"'); } } if ((typeInfo.Options & TypeInfo.Option.Version) != 0) { m_version = m_versionStack.Pop(); if (obj != null && newTypeInfo != null) { var source = new Convertible(typeInfo.Name, obj); var target = new Convertible(newTypeInfo.Name, null); source.ConvertInto(target); obj = target.Data; } } }
/// <summary> /// Returns whether a conversion will work or not. /// </summary> public bool IsConversionPossible(Convertible source, Convertible target) { return(IsConversionPossible(source.Descriptor, target.Descriptor)); }
/// <summary> /// Private helper for public Convert method above. /// </summary> private void Convert( Convertible source, Convertible target, Dictionary <string, Dictionary <string, RoutingEntry> > routingMap, List <Convertible> tempConvertibles) { var sourceDescr = source.Descriptor; var targetDescr = target.Descriptor; if (sourceDescr == targetDescr) { DirectConvert(source, target); return; } try { int distance = routingMap[sourceDescr][targetDescr].Distance; if (distance == 1 || distance == c_distanceComplex) { DirectConvert(source, target); if (tempConvertibles != null) { // dispose any temporary convertibles foreach (var temp in tempConvertibles) { if (!temp.Data.Equals(target.Data)) { var tempDisposable = temp.Data as IDisposable; if (tempDisposable != null) { tempDisposable.Dispose(); } } } tempConvertibles.Clear(); } } else if (distance < c_distanceUnreachable) { int lastDistance = FindLastDistance(sourceDescr, targetDescr); if ((distance < c_distanceComplex) || (lastDistance == c_distanceComplex)) { Convertible tmp = new Convertible(routingMap[sourceDescr][targetDescr].Next, null); DirectConvert(source, tmp); if (tempConvertibles == null) { tempConvertibles = new List <Convertible>(); } tempConvertibles.Add(tmp); Convert(tmp, target, routingMap, tempConvertibles); } else { throw new ConversionNotPossibleException(sourceDescr, targetDescr, "not reachable 1"); } } else { throw new ConversionNotPossibleException(sourceDescr, targetDescr, "not reachable 2"); } } catch (KeyNotFoundException) { throw new ConversionNotPossibleException(sourceDescr, targetDescr, "key not found"); } }
/// <summary> /// Converts the source convertible into the target convertible. /// There are 3 possibilities here: /// 1) There is a direct conversion possible, this works no matter if the conversion requires user-set parameters. /// 2) No direct conversion available. The conversion can be done indirectly in two cases: /// - there is no conversion with user parameters needed. /// - the only conversion with user parameters is the last one. /// ... in all other cases the conversion is not possible. /// 3) The conversion would need more than two conversion with user parameters, which can not be done. /// </summary> /// <param name="source">The source convertible</param> /// <param name="target">The target convertible (result will be stored in target.Data)</param> public void Convert(Convertible source, Convertible target) { Convert(source, target, CloneRoutingTable(), new List <Convertible>()); }
/// <summary> /// Returns a matching file convertible given a file name, taking a preferred target into account. /// Only works if a convertible was registered for the file extension (see RegisterExtension). /// </summary> public Convertible FindConvertibleByFileName(string fileName, Convertible preferrableTarget) { return(FindConvertibleByFileName(fileName, preferrableTarget.Descriptor)); }
/// <summary> /// Returns a matching raw convertible by also taking a preferred target into account. /// Only works if a raw convertible was registered (see RegisterRaw). /// </summary> public Convertible FindMatchingRaw(Convertible conv, Convertible preferrableTarget) { return(FindMatchingRaw(conv, preferrableTarget.Descriptor)); }