예제 #1
0
        SerializableType CompileType(Type type, bool describedOnly)
        {
            AmqpContract contract = this.contractResolver.Resolve(type);

            if (contract != null)
            {
                return(this.CreateContractType(contract));
            }

            return(this.CompileNonContractTypes(type));
        }
예제 #2
0
        SerializableType CompileType(Type type, bool describedOnly, HashSet <Type> pendingTypes)
        {
            AmqpContract contract = this.contractResolver.Resolve(type);

            if (contract != null)
            {
                return(this.CreateContractType(contract, pendingTypes));
            }

            return(this.CompileNonContractTypes(type, pendingTypes));
        }
예제 #3
0
        SerializableType CreateContractType(AmqpContract contract)
        {
            Type   type           = contract.Type;
            string descriptorName = contract.Attribute.Name;
            ulong? descriptorCode = contract.Attribute.InternalCode;

            if (descriptorName == null && descriptorCode == null)
            {
                descriptorName = type.FullName;
            }

            SerializableMember[] members = new SerializableMember[contract.Members.Length];
            for (int i = 0; i < contract.Members.Length; i++)
            {
                SerializableMember member = new SerializableMember();
                members[i] = member;

                AmqpMember amqpMember = contract.Members[i];
                member.Name     = amqpMember.Name;
                member.Order    = amqpMember.Order;
                member.Accessor = MemberAccessor.Create(amqpMember.Info, true);

                // This will recursively resolve member types
                Type memberType = amqpMember.Info is FieldInfo ?
                                  ((FieldInfo)amqpMember.Info).FieldType :
                                  ((PropertyInfo)amqpMember.Info).PropertyType;
                member.Type = GetType(memberType);
            }

            MethodAccessor[] serializationCallbacks = new MethodAccessor[]
            {
                contract.Serializing == null ? null : MethodAccessor.Create(contract.Serializing),
                contract.Serialized == null ? null : MethodAccessor.Create(contract.Serialized),
                contract.Deserializing == null ? null : MethodAccessor.Create(contract.Deserializing),
                contract.Deserialized == null ? null : MethodAccessor.Create(contract.Deserialized)
            };

            SerializableType baseType = null;

            if (contract.BaseContract != null)
            {
                baseType = this.CreateContractType(contract.BaseContract);
            }

            Dictionary <Type, SerializableType> knownTypes = null;

            if (contract.Provides != null)
            {
                knownTypes = new Dictionary <Type, SerializableType>();
                for (int i = 0; i < contract.Provides.Length; i++)
                {
                    // KnownType compilation is delayed and non-recursive to avoid circular references
                    knownTypes.Add(contract.Provides[i], null);
                }
            }

            if (contract.Attribute.Encoding == EncodingType.List)
            {
                return(SerializableType.CreateDescribedListType(this, type, baseType, descriptorName,
                                                                descriptorCode, members, knownTypes, serializationCallbacks));
            }
            else if (contract.Attribute.Encoding == EncodingType.Map)
            {
                return(SerializableType.CreateDescribedMapType(this, type, baseType, descriptorName,
                                                               descriptorCode, members, knownTypes, serializationCallbacks));
            }
            else if (contract.Attribute.Encoding == EncodingType.SimpleMap)
            {
                return(SerializableType.CreateDescribedSimpleMapType(this, type, baseType, members, serializationCallbacks));
            }
            else if (contract.Attribute.Encoding == EncodingType.SimpleList)
            {
                return(SerializableType.CreateDescribedSimpleListType(this, type, baseType, members, serializationCallbacks));
            }
            else
            {
                throw new NotSupportedException(contract.Attribute.Encoding.ToString());
            }
        }
예제 #4
0
        AmqpContract IContractResolver.Resolve(Type type)
        {
            AmqpContractAttribute contractAttribute = type.GetCustomAttribute <AmqpContractAttribute>(false);

            if (contractAttribute == null)
            {
                foreach (MemberInfo memberInfo in type.GetMembers(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))
                {
                    AmqpMemberAttribute attribute = memberInfo.GetCustomAttribute <AmqpMemberAttribute>(true);
                    if (attribute != null)
                    {
                        throw new AmqpException(ErrorCode.NotAllowed,
                                                Fx.Format("{0} has AmqpMemberAttribute members without AmqpContractAttribute on class", type.Name));
                    }
                }

                return(null);
            }

            if (contractAttribute.Encoding == EncodingType.SimpleMap &&
                type.GetCustomAttribute <AmqpProvidesAttribute>(false) != null)
            {
                throw new AmqpException(ErrorCode.NotAllowed,
                                        Fx.Format("{0}: SimpleMap encoding does not include descriptors so it does not support AmqpProvidesAttribute.", type.Name));
            }

            if (contractAttribute.Encoding == EncodingType.SimpleList &&
                type.GetCustomAttribute <AmqpProvidesAttribute>(false) != null)
            {
                throw new AmqpException(ErrorCode.NotAllowed,
                                        Fx.Format("{0}: SimpleList encoding does not include descriptors so it does not support AmqpProvidesAttribute.", type.Name));
            }

            AmqpContract baseContract = null;

            if (type.BaseType() != typeof(object))
            {
                baseContract = ((IContractResolver)this).Resolve(type.BaseType());
                if (baseContract != null && baseContract.Attribute.Encoding != contractAttribute.Encoding)
                {
                    throw new AmqpException(ErrorCode.NotAllowed,
                                            Fx.Format("{0}.Encoding ({1}) is different from {2}.Encoding ({3})",
                                                      type.Name, contractAttribute.Encoding, type.BaseType().Name, baseContract.Attribute.Encoding));
                }
            }

            string descriptorName = contractAttribute.Name;
            ulong? descriptorCode = contractAttribute.InternalCode;

            if (descriptorName == null && descriptorCode == null)
            {
                descriptorName = type.FullName;
            }

            var memberList = new List <AmqpMember>();
            int lastOrder  = 0;

            if (baseContract != null)
            {
                for (int i = 0; i < baseContract.Members.Length; i++)
                {
                    memberList.Add(baseContract.Members[i]);
                    lastOrder = Math.Max(lastOrder, baseContract.Members[i].Order);
                }
            }

            lastOrder++;
            MethodInfo serializing   = null;
            MethodInfo serialized    = null;
            MethodInfo deserializing = null;
            MethodInfo deserialized  = null;

            MemberInfo[] memberInfos = type.GetMembers(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
            foreach (MemberInfo memberInfo in memberInfos)
            {
                if (memberInfo.DeclaringType != type)
                {
                    continue;
                }

                if (memberInfo is FieldInfo || memberInfo is PropertyInfo)
                {
                    AmqpMemberAttribute attribute = memberInfo.GetCustomAttribute <AmqpMemberAttribute>(true);
                    if (attribute == null)
                    {
                        continue;
                    }

                    memberList.Add(new AmqpMember()
                    {
                        Attribute = attribute,
                        Info      = memberInfo,
                        Order     = attribute.InternalOrder ?? lastOrder++
                    });
                }
                else if (memberInfo is MethodInfo)
                {
                    if (memberInfo.GetCustomAttribute <OnSerializingAttribute>(false) != null)
                    {
                        serializing = (MethodInfo)memberInfo;
                    }
                    else if (memberInfo.GetCustomAttribute <OnSerializedAttribute>(false) != null)
                    {
                        serialized = (MethodInfo)memberInfo;
                    }
                    else if (memberInfo.GetCustomAttribute <OnDeserializingAttribute>(false) != null)
                    {
                        deserializing = (MethodInfo)memberInfo;
                    }
                    else if (memberInfo.GetCustomAttribute <OnDeserializedAttribute>(false) != null)
                    {
                        deserialized = (MethodInfo)memberInfo;
                    }
                }
            }

            if (contractAttribute.Encoding == EncodingType.List)
            {
                memberList.Sort(MemberOrderComparer.Instance);
                int order = -1;
                foreach (AmqpMember member in memberList)
                {
                    if (order > 0 && member.Order == order)
                    {
                        throw new AmqpException(ErrorCode.NotAllowed, Fx.Format("Duplicate Order {0} detected in {1}", order, type.Name));
                    }

                    order = member.Order;
                }
            }

            List <Type> knownTypes         = new List <Type>();
            var         providesAttributes = type.GetCustomAttributes <AmqpProvidesAttribute>(false);

            foreach (object o in providesAttributes)
            {
                AmqpProvidesAttribute knownAttribute = (AmqpProvidesAttribute)o;
                if (knownAttribute.Type.GetCustomAttribute <AmqpContractAttribute>(false) != null)
                {
                    knownTypes.Add(knownAttribute.Type);
                }
            }

            var contract = new AmqpContract(type)
            {
                Attribute     = contractAttribute,
                Members       = memberList.ToArray(),
                Provides      = knownTypes.ToArray(),
                Serializing   = serializing,
                Serialized    = serialized,
                Deserializing = deserializing,
                Deserialized  = deserialized,
                BaseContract  = baseContract
            };

            this.OnResolved(contract);

            return(contract);
        }
예제 #5
0
 /// <summary>
 /// Called when a type is successully resolved. Derived class can
 /// override this method to update the contract if necessary.
 /// </summary>
 /// <param name="contract">The serialization contract.</param>
 protected virtual void OnResolved(AmqpContract contract)
 {
 }
예제 #6
0
        SerializableType CreateContractType(AmqpContract contract, HashSet <Type> pendingTypes)
        {
            Type type = contract.Type;

            if (pendingTypes.Contains(type))
            {
                return(SerializableType.CreateDelegatingType(this, type));
            }

            pendingTypes.Add(type);
            string descriptorName = contract.Attribute.Name;
            ulong? descriptorCode = contract.Attribute.InternalCode;

            if (descriptorName == null && descriptorCode == null)
            {
                descriptorName = type.FullName;
            }

            SerializableMember[] members = new SerializableMember[contract.Members.Length];
            for (int i = 0; i < contract.Members.Length; i++)
            {
                SerializableMember member = new SerializableMember();
                members[i] = member;

                AmqpMember amqpMember = contract.Members[i];
                member.Name     = amqpMember.Name;
                member.Order    = amqpMember.Order;
                member.Accessor = MemberAccessor.Create(amqpMember.Info, true);

                // This will recursively resolve member types
                Type memberType = amqpMember.Info is FieldInfo ?
                                  ((FieldInfo)amqpMember.Info).FieldType :
                                  ((PropertyInfo)amqpMember.Info).PropertyType;
                member.Type = GetOrCompileType(memberType, false, pendingTypes);
            }

            MethodAccessor[] serializationCallbacks = new MethodAccessor[]
            {
                contract.Serializing == null ? null : MethodAccessor.Create(contract.Serializing),
                contract.Serialized == null ? null : MethodAccessor.Create(contract.Serialized),
                contract.Deserializing == null ? null : MethodAccessor.Create(contract.Deserializing),
                contract.Deserialized == null ? null : MethodAccessor.Create(contract.Deserialized)
            };

            SerializableType baseType = null;

            if (contract.BaseContract != null)
            {
                baseType = this.CreateContractType(contract.BaseContract, pendingTypes);
            }

            SerializableType[] knownTypes = null;
            if (contract.Provides != null)
            {
                knownTypes = new SerializableType[contract.Provides.Length];
                for (int i = 0; i < contract.Provides.Length; i++)
                {
                    knownTypes[i] = this.GetOrCompileType(contract.Provides[i], true, pendingTypes);
                }
            }

            SerializableType result;

            if (contract.Attribute.Encoding == EncodingType.List)
            {
                result = SerializableType.CreateDescribedListType(this, type, baseType, descriptorName,
                                                                  descriptorCode, members, knownTypes, serializationCallbacks);
            }
            else if (contract.Attribute.Encoding == EncodingType.Map)
            {
                result = SerializableType.CreateDescribedMapType(this, type, baseType, descriptorName,
                                                                 descriptorCode, members, knownTypes, serializationCallbacks);
            }
            else if (contract.Attribute.Encoding == EncodingType.SimpleMap)
            {
                result = SerializableType.CreateDescribedSimpleMapType(this, type, baseType, members, serializationCallbacks);
            }
            else if (contract.Attribute.Encoding == EncodingType.SimpleList)
            {
                result = SerializableType.CreateDescribedSimpleListType(this, type, baseType, members, serializationCallbacks);
            }
            else
            {
                throw new NotSupportedException(contract.Attribute.Encoding.ToString());
            }

            pendingTypes.Remove(type);
            return(result);
        }