public virtual void SetOutput(IValueItem item)
        {
            if (!AllowMultipleInputs)
            {
                foreach (var input in Inputs)
                    Repository.Remove(input);

            }
            if (!AllowMultipleOutputs)
            {
                foreach (var output in Outputs)
                    Repository.Remove(output);
            }


            var cd = new ConnectionData();
            cd.InputIdentifier = item.Identifier;
            cd.OutputIdentifier = Identifier;
            Repository.Add(cd);
        }
Exemple #2
0
        internal static IValueItem ReadTypeMetaInfo(IStreamReader reader, uint typeId, ISerializeContext ctx)
        {
            byte metaTypeVersion = reader.ReadUInt8();

            string assemblyName;
            string typeFullName;
            Type   type;

            if (metaTypeVersion == SingleTypeDescr)
            {
                assemblyName = reader.ReadString();
                typeFullName = reader.ReadString();

                if (!TypeService.TryGetTypeByName(typeFullName, out type, ctx.Serializer.CustomLookupAssemblies))
                {
                    if (ctx.Serializer.AutoCreateMissingTypes)
                    {
                        return(AutoCreateMissingDeserializeType(typeId, assemblyName, typeFullName, reader, ctx));
                    }
                    else
                    {
                        throw new TypeAccessException($"Type {typeFullName} not found!");
                    }
                }

                IValueItem resultItem = ctx.GetByType(type);

                if (resultItem is ITypeStructure)
                {
                    ITypeStructure result = (ITypeStructure)resultItem;

                    short itemCount = reader.ReadInt16();

                    if (result.TypeId == typeId)
                    {
                        // internal type is equal remote type
                        for (int i = 0; i < itemCount; i++)
                        {
                            SkipPropertyMetaInfo(reader);
                        }

                        return(result);
                    }
                    else
                    {
                        // differences between local type and remote type

                        // read actual structure and try map to old/new structure
                        ComplexStructure tolerantLayoutStructure = ComplexStructure.CreateTolerantLayoutStructure(type, ctx);

                        for (int i = 0; i < itemCount; i++)
                        {
                            ItemType itemType       = (ItemType)reader.ReadInt16(); // ItemType Enum
                            uint     propertyTypeId = reader.ReadUInt32();          // TypeId (Type Hash)
                            string   propertyName   = reader.ReadString();          // Property Name
                            bool     isNullable     = reader.ReadBool();            // Nullable Flag

                            IValueItem nameMatchingItem = result.Items.Where(item => item.Name == propertyName).FirstOrDefault();

                            if (nameMatchingItem != null)
                            {
                                bool typeMatch       = itemType == nameMatchingItem.Type;
                                bool typeIdMatch     = propertyTypeId == nameMatchingItem.TypeId;
                                bool nullableMatch   = isNullable == nameMatchingItem.IsNullable;
                                bool fromNotNullable = !isNullable && nameMatchingItem.IsNullable;

                                if (typeMatch &&
                                    typeIdMatch &&
                                    nullableMatch)
                                {
                                    // Property has exactly the same attributes > no conversion required
                                    tolerantLayoutStructure.AddTolerantLayoutProperty(ctx, propertyName);
                                }
                                else if (typeMatch &&
                                         typeIdMatch &&
                                         !nullableMatch &&
                                         fromNotNullable)
                                {
                                    // Property changed only from not nullable to nullable
                                    tolerantLayoutStructure.AddTolerantLayoutConverterProperty(nameMatchingItem, ctx, propertyName, itemType, propertyTypeId, isNullable, v => v);
                                }
                                else if (!typeMatch &&
                                         !typeIdMatch &&
                                         (nullableMatch || fromNotNullable))
                                {
                                    // Only property type changed
                                    // Check if type can be converted without loosing data
                                    Func <object, object> converter = null;
                                    if (itemType == ItemType.Int32 &&
                                        nameMatchingItem.Type == ItemType.Int64)
                                    {
                                        // Read incoming Int32 and convert to local Int64 property
                                        converter = v => (long)(int)v;
                                    }
                                    else if (itemType == ItemType.Int16 &&
                                             nameMatchingItem.Type == ItemType.Int32)
                                    {
                                        // Read incoming Int16 and convert to local Int32 property
                                        converter = v => (int)(short)v;
                                    }
                                    else if (itemType == ItemType.Byte &&
                                             nameMatchingItem.Type == ItemType.Int16)
                                    {
                                        // Read incoming Byte and convert to local Int16 property
                                        converter = v => (short)(byte)v;
                                    }
                                    else if (itemType == ItemType.Double &&
                                             nameMatchingItem.Type == ItemType.Decimal)
                                    {
                                        // Read incoming Double and convert to local Decimal property
                                        converter = v => (decimal)(double)v;
                                    }
                                    else if (itemType == ItemType.Char &&
                                             nameMatchingItem.Type == ItemType.String)
                                    {
                                        // Read incoming Char and convert to local String property
                                        converter = v => new string(new char[] { (char)v });
                                    }

                                    if (converter != null)
                                    {
                                        tolerantLayoutStructure.AddTolerantLayoutConverterProperty(nameMatchingItem, ctx, propertyName, itemType, propertyTypeId, isNullable, converter);
                                    }
                                }
                            }
                            else
                            {
                                // no name matching property found (removed, renamed or old local version) > create dummy item
                                tolerantLayoutStructure.AddTolerantLayoutDummyProperty(ctx, propertyName, itemType, propertyTypeId, isNullable);
                            }
                        }

                        tolerantLayoutStructure.FinalizeTolerantLayoutStructure();
                        if (typeId == tolerantLayoutStructure.TypeId)
                        {
                            // Tolerant mapping was successful
                            // Register only type ID in global cache
                            BinarySerializer.RegisterTolerantTypeMapping(tolerantLayoutStructure);

                            return(tolerantLayoutStructure);
                        }
                        else
                        {
                            // Can't map old/new structure to incoming type meta data
                            throw new FormatException($"The incoming binary format does not match the loaded type {type.FullName}! An tolerant mapping was not possible. Please update the remote or local interface assemblies. Expected Type Id: {result.TypeId}; Received Type Id: {typeId}");
                        }
                    }
                }
                else if (resultItem is ITypePrefix)
                {
                    // Only type prefix - e.g. enum
                    ITypePrefix result = (ITypePrefix)resultItem;

                    short itemCount = reader.ReadInt16();

                    if (result.TypeId == typeId)
                    {
                        // internal type is equal remote type
                        for (int i = 0; i < itemCount; i++)
                        {
                            SkipPropertyMetaInfo(reader);
                        }

                        return(result);
                    }
                    else
                    {
                        throw new FormatException($"The incoming binary format does not match the loaded type {type.FullName}! An tolerant mapping was not possible. Please update the remote or local interface assemblies. Expected Type Id: {result.TypeId}; Received Type Id: {typeId}");
                    }
                }
                else
                {
                    return(resultItem);
                }
            }
            else if (metaTypeVersion == CollectionTypeDescr)
            {
                assemblyName = reader.ReadString();
                typeFullName = reader.ReadString();

                //todo: load assembly if required
                if (TypeService.TryGetTypeByName(typeFullName, out type))
                {
                    CollectionItems result = (CollectionItems)ctx.GetByType(type);

                    if (result.TypeId == typeId)
                    {
                        return(result);
                    }
                    else
                    {
                        // differences between local type and remote type
                        //todo: implement
                        throw new NotImplementedException($"Support for different binary layout is not implemented yet! Local Type ID: {result.TypeId}; Remote Type ID: {typeId}");
                    }
                }
                else
                {
                    throw new TypeAccessException($"Type {typeFullName} not found!");
                }
            }
            else
            {
                throw new NotSupportedException($"Type meta information version {metaTypeVersion} not supported!");
            }
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="TolerantConvertItem" /> class.
 /// </summary>
 /// <param name="sourceTypeItem">The source type item.</param>
 /// <param name="targetTypeItem">The target type item.</param>
 /// <param name="converter">The converter.</param>
 public TolerantConvertItem(IValueItem sourceTypeItem, IValueItem targetTypeItem, Func <object, object> converter)
 {
     this.sourceTypeItem = sourceTypeItem;
     this.targetTypeItem = targetTypeItem;
     this.converter      = converter;
 }
Exemple #4
0
 internal bool TryGetDifferentTargetType(Type objectType, out IValueItem targetItem)
 {
     return(differentTargetTypes.TryGetValue(objectType, out targetItem));
 }
Exemple #5
0
        public void WriteValue(IStreamWriter writer, ISerializeContext context, object value)
        {
            // Complex structure
            // TypeID UInt32
            // ContentType Byte
            context.Key = this.Name;
            if (isObject)
            {
                // property or collection does not specify a target type
                // determine object type
                if (value != null)
                {
                    Type valType = value.GetType();

                    IValueItem item;
                    var        differentTargetStructure = context.DetermineSpecialInterfaceType(value.GetType(), type);
                    if (differentTargetStructure != null)
                    {
                        item = differentTargetStructure;
                    }
                    else
                    {
                        item = context.GetByType(valType);
                    }

                    if (!item.IsTypePrefixExpected)
                    {
                        // Write type id for value types as well (unknown structure)
                        writer.WriteUInt32(item.TypeId);

                        writer.WriteUInt8(ValueItem.SingleValueIdent);
                    }

                    item.WriteValue(writer, context, value);
                }
                else
                {
                    // write complex object type id for null value
                    writer.WriteInt32((int)ItemType.ComplexObject);
                    writer.WriteUInt8(ValueItem.NullValueIdent);
                }
            }
            else if (value == null)
            {
                // Write null
                writer.WriteUInt32(this.TypeId);
                writer.WriteUInt8(ValueItem.NullValueIdent);
            }
            else
            {
                IValueItem differentTargetStructure = null;
                if (CheckDifferentType)
                {
                    differentTargetStructure = context.DetermineSpecialInterfaceType(value.GetType(), type);
                }

                if (differentTargetStructure != null)
                {
                    // Special target interface type serialization
                    differentTargetStructure.WriteValue(writer, context, value);
                }
                else
                {
                    // Just write type properties
                    writer.WriteUInt32(this.TypeId);

                    if (context.IsWriteTypeMetaInfoRequired(this.TypeId))
                    {
                        // serialize type meta info at the first time
                        TypeMetaStructure.WriteTypeMetaInfo(writer, this);
                    }

                    writer.WriteUInt8(ValueItem.SingleObjectIdent);

                    object oldParentObj = context.ParentObject;
                    context.ParentObject = value;

                    for (int itemIndex = 0; itemIndex < items.Count; itemIndex++)
                    {
                        var item = items[itemIndex];

                        var valueItem = item.GetItemValue(value);

                        item.WriteValue(writer, context, valueItem);
                    }

                    context.ParentObject = oldParentObj;
                }
            }
        }
        //protected override Boolean ImplAddSequenceItem ( SequenceType sequence, Object item )
        //{
        //    if ( !(item is SequenceItemType) ) return false;

        //    SequenceItemType kvp = (SequenceItemType) item;

        //    try { sequence.Add ( kvp.Key, kvp.Value ); }
        //    catch { return false; }

        //    return true;
        //} // End of ImplAddSequenceItem (...)

        protected override Boolean ImplDeserializeItem(
            out Object retVal,
            Object item,
            IHierarchicalMetadataSerializationContext context)
        {
            retVal = null;

            IValueItem curCtxtLvlVi = null;
            KeyValuePair <SequenceKeyType,
                          SequenceValueType> kvp;
            IValueUnit        kvpVu;
            IValueUnit        kvpCtxtLvl = null;
            SequenceKeyType   kvpKey     = default(SequenceKeyType);
            SequenceValueType kvpValue   = default(SequenceValueType);
            IValueItem        valueItem  = null;

            if (context == null)
            {
                return(false);
            }
            if ((kvpVu = item as IValueUnit) == null)
            {
                return(false);
            }
            if (kvpVu.Count != 2)
            {
                return(false);
            }
            if ((kvpCtxtLvl = context.Hierarchy.Peek() as IValueUnit) == null)
            {
                return(false);
            }

            // Deserialize the Key
            if ((valueItem = kvpVu [nameof(kvp.Key)]) == null)
            {
                return(false);
            }

            if ((curCtxtLvlVi = kvpCtxtLvl [nameof(kvp.Key)]) == null)
            {
                context.Hierarchy.Push(null);
            }
            else
            {
                context.Hierarchy.Push(curCtxtLvlVi.Value as IValueUnit);
            }

            try
            {
                if (!base.ImplDeserializeItem(out Object key, valueItem.Value, context))
                {
                    return(false);
                }

                kvpKey = (SequenceKeyType)key;
            } finally { context.Hierarchy.Pop(); }


            // Deserialize the Value
            if ((valueItem = kvpVu [nameof(kvp.Value)]) == null)
            {
                return(false);
            }

            if ((curCtxtLvlVi = kvpCtxtLvl [nameof(kvp.Value)]) == null)
            {
                context.Hierarchy.Push(null);
            }
            else
            {
                context.Hierarchy.Push(curCtxtLvlVi.Value as IValueUnit);
            }

            try
            {
                if (!base.ImplDeserializeItem(out Object value, valueItem.Value, context))
                {
                    return(false);
                }

                kvpValue = (SequenceValueType)value;
            } finally { context.Hierarchy.Pop(); }

            kvp    = new KeyValuePair <SequenceKeyType, SequenceValueType> (kvpKey, kvpValue);
            retVal = kvp;

            return(true);
        } // End of ImplDeserializeItem (...)
Exemple #7
0
        /// <summary>
        /// Initializes a new instance of the <see cref="CollectionItems"/> class.
        /// </summary>
        /// <param name="type">The type.</param>
        public CollectionItems(Type type, string name, Func <object, object> getter, Action <object, object> setter, ITypeResolver typeResolver)
        {
            this.type = type;
            if (name != null)
            {
                this.Name = name;
            }
            else
            {
                this.Name = type.FullName;
            }
            this.isArray = type.IsArray;
            this.setter  = setter;
            this.getter  = getter;
            this.typeId  = CalculateTypeId();

            if (isArray)
            {
                itemType    = type.GetElementType();
                isByteArray = itemType.Equals(typeof(byte));
            }
            else
            {
                // type is a collection
                // check if collection is generic IEnumerable<T>
                if (type.IsGenericType)
                {
                    Type   genericCollectionInterface = type.GetInterface("IEnumerable`1");
                    Type[] genericTypes = type.GetGenericArguments();
                    if (genericTypes.Length == 1)
                    {
                        Type listType = typeof(List <>);
                        targetCollectionType = listType.MakeGenericType(genericTypes);
                        itemType             = genericTypes[0];
                    }
                    else if (genericTypes.Length == 0 &&
                             genericCollectionInterface != null)
                    {
                        genericTypes = genericCollectionInterface.GetGenericArguments();
                        Type listType = typeof(List <>);
                        targetCollectionType = listType.MakeGenericType(genericTypes);
                        itemType             = genericTypes[0];
                    }
                    else
                    {
                        throw new NotImplementedException("More than one generic arguments is not supported yet!");
                    }
                }
                else
                {
                    var defaultConstructor = type.GetConstructor(System.Type.EmptyTypes);

                    if (defaultConstructor != null)
                    {
                        targetCollectionType = type;
                    }
                    else
                    {
                        // untyped collection
                        targetCollectionType = typeof(ArrayList);
                    }
                    itemType = typeof(object);
                }

                implementsIList = targetCollectionType.GetInterface("IList") != null;
                if (!implementsIList)
                {
                    specialCollAddMethod = targetCollectionType.GetMethod("Add");
                }
            }

            itemStructure = typeResolver.GetByType(itemType);
        }