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()); }
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()); }
private SerializerPair GetOrRegisterStaticSerializerInternal(Type type, bool instance) { if (ReflectionSerializerVerifier.IsScalar(type)) { return(GetOrCreateScalar(type, instance)); } // RdModels only if (!mySerializers.TryGetValue(type, out var serializerPair)) { #if JET_MODE_ASSERT myCurrentSerializersChain.Enqueue(type); #endif using (new FirstChanceExceptionInterceptor.ThreadLocalDebugInfo(type)) { if (ReflectionSerializerVerifier.HasIntrinsicFields(type.GetTypeInfo())) { mySerializers.Add(type, Intrinsic.TryGetIntrinsicSerializer( type.GetTypeInfo(), _ => throw new InvalidOperationException("Generic models are not supported"))); } else { ReflectionUtil.InvokeGenericThis(this, nameof(RegisterModelSerializer), type); } } #if JET_MODE_ASSERT myCurrentSerializersChain.Dequeue(); #endif if (!mySerializers.TryGetValue(type, out serializerPair)) { throw new KeyNotFoundException($"Unable to register type {type.ToString(true)}: serializer can't be found"); } } Assertion.AssertNotNull(serializerPair, $"Unable to register type: {type.ToString(true)}, undetected circular dependency."); if (instance && !type.IsSealed) { return(GetPolymorphic(type)); } return(serializerPair); }
/// <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);
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); } }
private SerializerPair GetOrRegisterStaticSerializerInternal(Type type, bool instance) { if (!mySerializers.TryGetValue(type, out var serializerPair)) { #if JET_MODE_ASSERT myCurrentSerializersChain.Enqueue(type); #endif if (ReflectionSerializerVerifier.IsScalar(type)) { return(GetOrCreateScalar(type, instance)); } else { ReflectionUtil.InvokeGenericThis(this, nameof(RegisterModelSerializer), type); } #if JET_MODE_ASSERT myCurrentSerializersChain.Dequeue(); #endif if (!mySerializers.TryGetValue(type, out serializerPair)) { throw new KeyNotFoundException($"Unable to register type {type.ToString(true)}: serializer can't be found"); } } Assertion.AssertNotNull(serializerPair, $"Unable to register type: {type.ToString(true)}, undetected circular dependency."); if (instance && CanBePolymorphicRdModel(type)) { return(GetPolymorphic(type)); } return(serializerPair); }