コード例 #1
0
        internal static FieldInfo[] GetBindableMembers(TypeInfo typeInfo)
        {
/*
 *    var rpcInterface = GetRpcInterface();
 *    if (rpcInterface != null)
 *    {
 *      var rpcInterfaceMap = typeInfo.GetInterfaceMap(rpcInterface);
 *      //members = rpcInterfaceMap.TargetMethods;
 *    }
 */
            Type baseType;

            if (ReflectionSerializerVerifier.HasRdExtAttribute(typeInfo))
            {
                baseType = typeof(RdExtReflectionBindableBase);
            }
            else if (ReflectionSerializerVerifier.HasRdModelAttribute(typeInfo))
            {
                baseType = typeof(RdReflectionBindableBase);
            }
            else
            {
                baseType = typeof(RdBindableBase);
            }

            bool isRdExtImpl      = baseType == typeof(RdExtReflectionBindableBase) && !typeInfo.GetInterfaces().Contains(typeof(IProxyTypeMarker));
            bool isRdRpcInterface = typeInfo.IsInterface; // can be specified in RdExt // && typeInfo.GetCustomAttribute<RdRpcAttribute>() != null;

            var fields = GetFields(typeInfo, baseType);
            var list   = new List <FieldInfo>();

            foreach (var mi in fields)
            {
                if (typeof(RdExtReflectionBindableBase).IsAssignableFrom(mi.FieldType))
                {
                    continue;
                }

                if (
                    mi.MemberType == MemberTypes.Field &&
                    (mi.DeclaringType != null && !mi.DeclaringType.GetTypeInfo().IsAssignableFrom(baseType)) &&
                    mi.GetCustomAttribute <NonSerializedAttribute>() == null &&

                    // arbitrary data is allowed in RdExt implementations since they don't have to be serializable
                    !(isRdExtImpl && ReflectionSerializerVerifier.IsScalar(ReflectionSerializerVerifier.GetImplementingType(mi.FieldType.GetTypeInfo())))
                    )
                {
                    list.Add(mi);
                }
                else if (isRdRpcInterface)
                {
                    throw new Exception($"Invalid member in RdRpc interface: {typeInfo.ToString(true)}.{mi.Name}");
                }
            }

            return(list.ToArray());
        }
コード例 #2
0
        internal static FieldInfo[] GetBindableMembers(TypeInfo typeInfo)
        {
/*
 *    var rpcInterface = GetRpcInterface();
 *    if (rpcInterface != null)
 *    {
 *      var rpcInterfaceMap = typeInfo.GetInterfaceMap(rpcInterface);
 *      //members = rpcInterfaceMap.TargetMethods;
 *    }
 */
            Type baseType;

            if (ReflectionSerializerVerifier.HasRdExtAttribute(typeInfo))
            {
                baseType = typeof(RdExtReflectionBindableBase);
            }
            else if (ReflectionSerializerVerifier.HasRdModelAttribute(typeInfo))
            {
                baseType = typeof(RdReflectionBindableBase);
            }
            else
            {
                baseType = typeof(RdBindableBase);
            }

            bool isRdExt = baseType == typeof(RdExtReflectionBindableBase);

            var members = GetFields(typeInfo, baseType);
            var list    = new List <FieldInfo>();

            foreach (var mi in members)
            {
                if (
                    mi.MemberType == MemberTypes.Field &&
                    (mi.DeclaringType != null && !mi.DeclaringType.GetTypeInfo().IsAssignableFrom(baseType)) &&
                    mi.GetCustomAttribute <NonSerializedAttribute>() == null &&

                    // arbitrary data is allowed in RdExt since they don't have to be serializable
                    !(isRdExt && ReflectionSerializerVerifier.IsScalar(ReflectionSerializerVerifier.GetImplementingType(mi.FieldType.GetTypeInfo())))
                    )
                {
                    list.Add(mi);
                }
            }

            return(list.ToArray());
        }
コード例 #3
0
        private SerializerPair GetMemberSerializer(MemberInfo member, TypeInfo typeInfo)
        {
            var implementingType     = ReflectionSerializerVerifier.GetImplementingType(typeInfo);
            var implementingTypeInfo = implementingType.GetTypeInfo();

            if (mySerializers.TryGetValue(typeInfo.AsType(), out var pair))
            {
                return(pair);
            }

            if (ReflectionSerializerVerifier.IsValueTuple(implementingTypeInfo))
            {
                return((SerializerPair)ReflectionUtil.InvokeGenericThis(this, nameof(CreateValueTupleSerializer), typeInfo.AsType()));
            }

            var hasRdAttribute = ReflectionSerializerVerifier.HasRdModelAttribute(typeInfo) || ReflectionSerializerVerifier.HasRdExtAttribute(typeInfo);

            if (typeInfo.IsGenericType && !hasRdAttribute)
            {
                return(CreateGenericSerializer(member, typeInfo, implementingType, implementingTypeInfo));
            }

            if (typeInfo.IsEnum)
            {
                var serializer = ReflectionUtil.InvokeGenericThis(this, nameof(CreateEnumSerializer), typeInfo.AsType());
                return((SerializerPair)serializer);
            }

            if (typeInfo.IsArray)
            {
                var serializer = ReflectionUtil.InvokeGenericThis(this, nameof(CreateArraySerializer), typeInfo.GetElementType());
                return((SerializerPair)serializer);
            }

            if (hasRdAttribute)
            {
                return(GetOrRegisterSerializerInternal(typeInfo.AsType()));
            }

            Assertion.Fail($"Unable to serialize member: {member.DeclaringType?.ToString(true)}.{member.Name} of type {typeInfo.ToString(true)}");

            return(null);
        }
コード例 #4
0
        /// <summary>
        /// Register serializers for either <see cref="RdExtAttribute"/> or <see cref="RdModelAttribute"/>
        /// </summary>
        private void RegisterModelSerializer <T>()
        {
            Assertion.Assert(!ReflectionSerializerVerifier.IsScalar(typeof(T)), "Type {0} should be either RdModel or RdExt.", typeof(T));
            // place null marker to detect circular dependencies
            mySerializers.Add(typeof(T), null);

            TypeInfo typeInfo = typeof(T).GetTypeInfo();

            ReflectionSerializerVerifier.AssertRoot(typeInfo);
            var  isScalar      = ReflectionSerializerVerifier.IsScalar(typeInfo);
            bool allowNullable = ReflectionSerializerVerifier.HasRdModelAttribute(typeInfo) || (isScalar && ReflectionSerializerVerifier.CanBeNull(typeInfo));

/*      var intrinsicSerializer = TryGetIntrinsicSerializer(typeInfo);
 *    if (intrinsicSerializer != null)
 *    {
 *      mySerializers[typeof(T)] = intrinsicSerializer;
 *      return;
 *    }*/

            var memberInfos   = SerializerReflectionUtil.GetBindableMembers(typeInfo);
            var memberSetters = memberInfos.Select(ReflectionUtil.GetSetter).ToArray();
            var memberGetters = memberInfos.Select(ReflectionUtil.GetGetter).ToArray();

            // todo: consider using IL emit
            var memberDeserializers = new CtxReadDelegate <object> [memberInfos.Length];
            var memberSerializers   = new CtxWriteDelegate <object> [memberInfos.Length];

            for (var index = 0; index < memberInfos.Length; index++)
            {
                var mi         = memberInfos[index];
                var returnType = ReflectionUtil.GetReturnType(mi);
                var serPair    = GetOrCreateMemberSerializer(mi, serializerType: returnType, allowNullable: allowNullable);
                memberDeserializers[index] = SerializerReflectionUtil.ConvertReader(returnType, serPair.Reader);
                memberSerializers[index]   = SerializerReflectionUtil.ConvertWriter(returnType, serPair.Writer);
            }

            var type = typeInfo.AsType();

            CtxReadDelegate <T> readerDelegate = (ctx, unsafeReader) =>
            {
                if (allowNullable && !unsafeReader.ReadNullness())
                {
                    return(default);
コード例 #5
0
        internal SerializerPair GetOrCreateMemberSerializer([NotNull] MemberInfo mi, [NotNull] Type serializerType, bool allowNullable)
        {
            if (!allowNullable)
            {
                ReflectionSerializerVerifier.AssertMemberDeclaration(mi);
            }
            else
            {
                ReflectionSerializerVerifier.AssertDataMemberDeclaration(mi);
            }

            var typeInfo             = serializerType.GetTypeInfo();
            var implementingType     = ReflectionSerializerVerifier.GetImplementingType(typeInfo);
            var implementingTypeInfo = implementingType.GetTypeInfo();

            if (typeInfo.IsGenericType && !(ReflectionSerializerVerifier.HasRdModelAttribute(typeInfo) || ReflectionSerializerVerifier.HasRdExtAttribute(typeInfo)))
            {
                return(CreateGenericSerializer(mi, typeInfo, implementingType));
            }
            else if (ReflectionSerializerVerifier.IsScalar(serializerType))
            {
                return(GetOrCreateScalar(serializerType, false));
            }
            else
            {
                var serializerPair = GetOrRegisterStaticSerializerInternal(serializerType, false);
                Assertion.AssertNotNull(serializerPair != null, $"Unable to Create serializer for type {serializerType.ToString(true)}");
                if (serializerPair == null)
                {
#if JET_MODE_ASSERT
                    Assertion.Fail($"Unable to create serializer for {serializerType.ToString(true)}: circular dependency detected: {String.Join(" -> ", myCurrentSerializersChain.Select(t => t.ToString(true)).ToArray())}");
#endif
                    throw new Assertion.AssertionException($"Undetected circular dependency during serializing {serializerType.ToString(true)}");
                }

                return(serializerPair);
            }
        }
コード例 #6
0
        /// <summary>
        /// Register serializers for either <see cref="RdExtAttribute"/> or <see cref="RdModelAttribute"/>
        /// </summary>
        private void RegisterModelSerializer <T>()
        {
            // place null marker to detect circular dependencies
            mySerializers.Add(typeof(T), null);

            TypeInfo typeInfo = typeof(T).GetTypeInfo();

            ReflectionSerializerVerifier.AssertRoot(typeInfo);
            bool allowNullable = ReflectionSerializerVerifier.HasRdModelAttribute(typeInfo);

            var intrinsicSerializer = TryGetIntrinsicSerializer(typeInfo);

            if (intrinsicSerializer != null)
            {
                mySerializers[typeof(T)] = intrinsicSerializer;
                return;
            }

            var memberInfos   = GetBindableMembers(typeInfo);
            var memberSetters = memberInfos.Select(ReflectionUtil.GetSetter).ToArray();
            var memberGetters = memberInfos.Select(ReflectionUtil.GetGetter).ToArray();

            // todo: consider using IL emit
            var memberDeserializers = new CtxReadDelegate <object> [memberInfos.Length];
            var memberSerializers   = new CtxWriteDelegate <object> [memberInfos.Length];

            for (var index = 0; index < memberInfos.Length; index++)
            {
                var mi         = memberInfos[index];
                var returnType = ReflectionUtil.GetReturnType(mi);
                var serPair    = GetOrCreateMemberSerializer(mi, serializerType: returnType, allowNullable: allowNullable);
                memberDeserializers[index] = ConvertReader(returnType, serPair.Reader);
                memberSerializers[index]   = ConvertWriter(returnType, serPair.Writer);
            }

            var type = typeInfo.AsType();
            CtxReadDelegate <T> readerDelegate = (ctx, unsafeReader) =>
            {
                // todo: support non-default constructors
                var instance = Activator.CreateInstance(type);

                var  bindableInstance = instance as IRdBindable;
                RdId id = default(RdId);
                if (bindableInstance != null)
                {
                    id = unsafeReader.ReadRdId();
                }

                for (var index = 0; index < memberDeserializers.Length; index++)
                {
                    var value = memberDeserializers[index](ctx, unsafeReader);
                    memberSetters[index](instance, value);
                }

                bindableInstance?.WithId(id);

                return((T)instance);
            };

            CtxWriteDelegate <T> writerDelegate = (ctx, unsafeWriter, value) =>
            {
                if (value is IRdBindable bindableInstance)
                {
                    unsafeWriter.Write(bindableInstance.RdId);
                }

                for (var i = 0; i < memberDeserializers.Length; i++)
                {
                    var memberValue = memberGetters[i](value);
                    memberSerializers[i](ctx, unsafeWriter, memberValue);
                }
            };

            mySerializers[type] = new SerializerPair(readerDelegate, writerDelegate);
        }