示例#1
0
        /// <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);
        }
示例#2
0
        /// <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);
        }
示例#3
0
        /// <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);
        }
示例#4
0
        /// <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);
        }
示例#5
0
        /// <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");
            }
        }
示例#6
0
        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;
                }
            }
        }
示例#7
0
 /// <summary>
 /// Returns whether a conversion will work or not.
 /// </summary>
 public bool IsConversionPossible(Convertible source, Convertible target)
 {
     return(IsConversionPossible(source.Descriptor, target.Descriptor));
 }
示例#8
0
        /// <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");
            }
        }
示例#9
0
 /// <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>());
 }
示例#10
0
 /// <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));
 }
示例#11
0
 /// <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));
 }