private SerializerPair GetOrCreateMemberSerializer([NotNull] MemberInfo mi, [NotNull] Type serializerType, bool allowNullable) { if (!allowNullable) { ReflectionSerializerVerifier.AssertMemberDeclaration(mi); } else { ReflectionSerializerVerifier.AssertDataMemberDeclaration(mi); } if (!mySerializers.TryGetValue(serializerType, out var serializerPair)) { serializerPair = GetMemberSerializer(mi, serializerType.GetTypeInfo()); Assertion.AssertNotNull(serializerPair != null, $"Unable to Create serializer for type {serializerType.ToString(true)}"); mySerializers[serializerType] = serializerPair; } 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 => Types.ToString(t, true)).ToArray())}"); #endif throw new Assertion.AssertionException($"Undetected circular dependency during serializing {serializerType.ToString(true)}"); } return(serializerPair); }
private object ActivateRd(Type type) { #if JET_MODE_ASSERT Assertion.Assert(!myCurrentActivationChain.Contains(type), $"Unable to activate {type.FullName}: circular dependency detected: {string.Join(" -> ", myCurrentActivationChain.Select(t => t.FullName).ToArray())}"); myCurrentActivationChain.Enqueue(type); #endif var typeInfo = type.GetTypeInfo(); ReflectionSerializerVerifier.AssertEitherExtModelAttribute(typeInfo); var implementingType = ReflectionSerializerVerifier.GetImplementingType(typeInfo); Assertion.Assert(typeof(RdBindableBase).GetTypeInfo().IsAssignableFrom(implementingType), $"Unable to activate {type.FullName}: type should be {nameof(RdBindableBase)}"); object instance; try { instance = Activator.CreateInstance(implementingType); } catch (MissingMethodException e) { throw new MissingMethodException($"Unable to create instance of: {implementingType.ToString(true)}.{e.Message}"); } ReflectionInitInternal(instance); #if JET_MODE_ASSERT myCurrentActivationChain.Dequeue(); #endif return(instance); }
private object ActivateRdExtMember(MemberInfo mi) { var returnType = ReflectionUtil.GetReturnType(mi); var typeInfo = returnType.GetTypeInfo(); var implementingType = ReflectionSerializerVerifier.GetImplementingType(typeInfo); object result; if (implementingType.GetTypeInfo().IsGenericType) { result = ActivateGenericMember(mi.Name, typeInfo); } else { result = ActivateRd(returnType); } if (result is IRdReactive activatedBindable) { foreach (var _ in mi.GetCustomAttributes(typeof(RdAsyncAttribute), false)) { activatedBindable.Async = true; } } return(result); }
private SerializerPair CreateCustomScalar <T>() { if (typeof(IRdBindable).IsAssignableFrom(typeof(T))) { Assertion.Fail($"Invalid scalar type: {typeof(T).ToString(true)}. Scalar types cannot be IRdBindable."); } if (typeof(T).IsInterface || typeof(T).IsAbstract) { Assertion.Fail($"Invalid scalar type: {typeof(T).ToString(true)}. Scalar types should be concrete types."); } TypeInfo typeInfo = typeof(T).GetTypeInfo(); var allowNullable = ReflectionSerializerVerifier.CanBeNull(typeInfo); 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]; CtxReadDelegate <T> readerDelegate = (ctx, unsafeReader) => { if (allowNullable && !unsafeReader.ReadNullness()) { return(default);
private SerializerPair TryGetIntrinsicSerializer(TypeInfo typeInfo) { if (!ReflectionSerializerVerifier.HasIntrinsicMethods(typeInfo)) { return(null); } var genericArguments = typeInfo.GetGenericArguments(); if (genericArguments.Length == 1) { var argument = genericArguments[0]; var staticRead = GetReadStaticSerializer(typeInfo, argument); var staticWrite = GetWriteStaticDeserializer(typeInfo); return(SerializerPair.CreateFromMethods(staticRead, staticWrite, GetOrRegisterSerializerInternal(argument))); } if (genericArguments.Length == 0) { var staticRead = GetReadStaticSerializer(typeInfo); var staticWrite = GetWriteStaticDeserializer(typeInfo); return(SerializerPair.CreateFromMethods(staticRead, staticWrite)); } return(null); }
private object ActivateGenericMember(string memberName, TypeInfo memberType) { var implementingType = ReflectionSerializerVerifier.GetImplementingType(memberType); var genericDefinition = implementingType.GetGenericTypeDefinition(); var genericArguments = implementingType.GetTypeInfo().GetGenericArguments(); var argument = genericArguments[0]; var serializerPair = GetProperSerializer(argument); if (genericDefinition == typeof(RdProperty <>) || genericDefinition == typeof(RdSignal <>) || genericDefinition == typeof(RdSet <>)) { return(Activator.CreateInstance(implementingType, serializerPair.Reader, serializerPair.Writer)); } if (genericDefinition == typeof(RdList <>)) { return(Activator.CreateInstance(implementingType, serializerPair.Reader, serializerPair.Writer, 1L /*nextVersion*/)); } if (genericDefinition == typeof(RdMap <,>) || genericDefinition == typeof(InprocRpc <,>) || genericDefinition == typeof(RdCall <,>) || genericDefinition == typeof(RdCall <,>)) { var argument2 = genericArguments[1]; var serializerPair2 = GetProperSerializer(argument2); var instance = Activator.CreateInstance(implementingType, serializerPair.Reader, serializerPair.Writer, serializerPair2.Reader, serializerPair2.Writer); if (ourLog.IsTraceEnabled()) { ourLog.Trace("Create RdCall: {0}.{1}, TReq poly: {2}, TRes poly: {3}", implementingType.FullName, memberName, serializerPair.IsPolymorphic, serializerPair2.IsPolymorphic); } ((RdReactiveBase)instance).ValueCanBeNull = true; return(instance); } if (genericDefinition == typeof(Nullable <>)) { // already initialized to null return(null); } // hack for UProperty & USignal if (genericArguments.Length == 1 && (typeof(IViewableProperty <>).MakeGenericType(genericArguments).GetTypeInfo().IsAssignableFrom(implementingType) || typeof(ISignal <>).MakeGenericType(genericArguments).GetTypeInfo().IsAssignableFrom(implementingType) )) { foreach (var ctor in implementingType.GetTypeInfo().GetConstructors(BindingFlags.Public | BindingFlags.Instance)) { var parameters = ctor.GetParameters(); if (parameters.Length == 3 && parameters[0].Name == "id") { return(Activator.CreateInstance(implementingType, memberName, serializerPair.Reader, serializerPair.Writer)); } } } throw new Exception($"Unable to activate generic type: {memberType}"); }
/// <summary> /// Return static serializers for type /// </summary> /// <param name="type"></param> /// <returns></returns> public SerializerPair GetOrCreate(Type type) { if (myStaticSerializers.TryGetValue(type, out var pair)) { return(pair); } var result = CreateSerializer(type); myStaticSerializers[type] = result; return(result); SerializerPair CreateSerializer(Type t) { var typeInfo = t.GetTypeInfo(); var intrinsic = TryGetIntrinsicSerializer(typeInfo); if (intrinsic != null) { myTypesCatalog.AddType(type); return(intrinsic); } if (IsList(t)) { var genericTypeArgument = t.GetGenericArguments()[0]; var argumentTypeSerializerPair = GetInstanceSerializer(genericTypeArgument); return((SerializerPair)ReflectionUtil.InvokeStaticGeneric(typeof(CollectionSerializers), nameof(CollectionSerializers.CreateListSerializerPair), genericTypeArgument, argumentTypeSerializerPair)); } else if (t.IsArray) { return((SerializerPair)ReflectionUtil.InvokeGenericThis(this, nameof(CreateArraySerializer), t.GetElementType())); } else if (t.IsEnum) { var serializer = ReflectionUtil.InvokeGenericThis(this, nameof(CreateEnumSerializer), t); return((SerializerPair)serializer); } else if (ReflectionSerializerVerifier.IsValueTuple(typeInfo)) { return((SerializerPair)ReflectionUtil.InvokeGenericThis(this, nameof(CreateValueTupleSerializer), type)); } else if (typeInfo.IsGenericType && typeInfo.GetGenericTypeDefinition() == typeof(Nullable <>)) { var genericTypeArgument = typeInfo.GetGenericArguments()[0]; var nullableSerializer = (SerializerPair)ReflectionUtil.InvokeGenericThis(this, nameof(RegisterNullable), genericTypeArgument); return(nullableSerializer); // return CreateGenericSerializer(member, typeInfo, implementingType, implementingTypeInfo); } else { myTypesCatalog.AddType(type); var serializer = ReflectionUtil.InvokeGenericThis(this, nameof(CreateCustomScalar), t); return((SerializerPair)serializer); } } }
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()); }
private object ActivateGenericMember(string memberName, TypeInfo memberType) { var implementingType = ReflectionSerializerVerifier.GetImplementingType(memberType); var genericDefinition = implementingType.GetGenericTypeDefinition(); var genericArguments = implementingType.GetTypeInfo().GetGenericArguments(); var argument = genericArguments[0]; var serializerPair = GetProperSerializer(argument); if (genericDefinition == typeof(RdProperty <>) || genericDefinition == typeof(RdSignal <>) || genericDefinition == typeof(RdList <>) || genericDefinition == typeof(RdSet <>)) { return(Activator.CreateInstance(implementingType, serializerPair.Reader, serializerPair.Writer)); } if (genericDefinition == typeof(RdMap <,>)) { var argument2 = genericArguments[1]; var serializerPair2 = GetProperSerializer(argument2); return(Activator.CreateInstance(implementingType, serializerPair.Reader, serializerPair.Writer, serializerPair2.Reader, serializerPair2.Writer)); } if (genericDefinition == typeof(InprocRpc <,>)) { var rpcResultType = genericArguments[1]; GetProperSerializer(rpcResultType); return(Activator.CreateInstance(implementingType)); } if (genericDefinition == typeof(Nullable <>)) { // already initialized to null return(null); } // hack for UProperty if (genericArguments.Length == 1 && typeof(IViewableProperty <>).MakeGenericType(genericArguments).GetTypeInfo().IsAssignableFrom(implementingType)) { foreach (var ctor in implementingType.GetTypeInfo().GetConstructors(BindingFlags.Public | BindingFlags.Instance)) { var parameters = ctor.GetParameters(); if (parameters.Length == 3 && parameters[0].Name == "id") { return(Activator.CreateInstance(implementingType, memberName, serializerPair.Reader, serializerPair.Writer)); } } } throw new Exception($"Unable to activate generic type: {memberType}"); }
public Type CreateType <TInterface>() where TInterface : class { if (!typeof(TInterface).IsInterface) { throw new ArgumentException("Only interfaces are supported."); } if (typeof(TInterface).GetGenericArguments().Length > 0) { throw new ArgumentException("Generic interfaces are not supported."); } if (!ReflectionSerializerVerifier.IsRpcAttributeDefined(typeof(TInterface))) { throw new ArgumentException($"Unable to create proxy for {typeof(TInterface)}. No {nameof(RdRpcAttribute)} specified."); } var moduleBuilder = myModuleBuilder.Value; var className = typeof(TInterface).Name.Substring(1); var proxyTypeName = "Proxy." + className; var typebuilder = moduleBuilder.DefineType( proxyTypeName, TypeAttributes.NotPublic | TypeAttributes.Class | TypeAttributes.Sealed, typeof(RdExtReflectionBindableBase)); // Implement interface typebuilder.AddInterfaceImplementation(typeof(TInterface)); // mark it as proxy type typebuilder.AddInterfaceImplementation(typeof(IProxyTypeMarker)); // Add RdExt attribute to type var rdExtConstructor = typeof(RdExtAttribute).GetConstructors()[0]; typebuilder.SetCustomAttribute(new CustomAttributeBuilder(rdExtConstructor, new object[0])); var memberNames = new HashSet <string>(StringComparer.Ordinal); var members = typeof(TInterface).GetMembers(BindingFlags.Instance | BindingFlags.Public); foreach (var member in members) { if (!memberNames.Add(member.Name)) { throw new ArgumentException($"Duplicate member name: {member.Name}. Method overloads are not supported."); } ImplementMember <TInterface>(typebuilder, member); } #if NET35 return(typebuilder.CreateType()); #else return(typebuilder.CreateTypeInfo()); #endif }
public static Type GetRpcInterface(TypeInfo typeInfo) { foreach (var @interface in typeInfo.GetInterfaces()) { if (ReflectionSerializerVerifier.IsRpcAttributeDefined(@interface)) { return(@interface); } } return(null); }
/// <summary> /// Register serializer for ValueTuples /// </summary> private SerializerPair CreateValueTupleSerializer <T>() { TypeInfo typeInfo = typeof(T).GetTypeInfo(); ReflectionSerializerVerifier.AssertRoot(typeInfo); var argumentTypes = typeInfo.GetGenericArguments(); var memberGetters = typeInfo.GetFields().Select(ReflectionUtil.GetGetter).ToArray(); var memberDeserializers = new CtxReadDelegate <object> [argumentTypes.Length]; var memberSerializers = new CtxWriteDelegate <object> [argumentTypes.Length]; for (var index = 0; index < argumentTypes.Length; index++) { var argumentType = argumentTypes[index]; var serPair = GetOrRegisterSerializerInternal(argumentType); memberDeserializers[index] = ConvertReader(argumentType, serPair.Reader); memberSerializers[index] = ConvertWriter(argumentType, serPair.Writer); } var type = typeInfo.AsType(); CtxReadDelegate <T> readerDelegate = (ctx, unsafeReader) => { // todo: consider using IL emit var activatorArgs = new object[argumentTypes.Length]; for (var index = 0; index < argumentTypes.Length; index++) { var value = memberDeserializers[index](ctx, unsafeReader); activatorArgs[index] = value; } var instance = Activator.CreateInstance(type, activatorArgs); return((T)instance); }; CtxWriteDelegate <T> writerDelegate = (ctx, unsafeWriter, value) => { for (var i = 0; i < argumentTypes.Length; i++) { var memberValue = memberGetters[i](value); memberSerializers[i](ctx, unsafeWriter, memberValue); } }; return(new SerializerPair(readerDelegate, writerDelegate)); }
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); }
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()); }
public static Type GetRpcInterface(TypeInfo typeInfo) { if (typeInfo.GetCustomAttribute <RdExtAttribute>() is RdExtAttribute rdExt && rdExt.RdRpcInterface != null) { return(rdExt.RdRpcInterface); } foreach (var @interface in typeInfo.GetInterfaces()) { if (ReflectionSerializerVerifier.IsRpcAttributeDefined(@interface)) { return(@interface); } } return(null); }
/// <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);
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); }
internal static MemberInfo[] GetBindableMembers(TypeInfo typeInfo) { ReflectionSerializerVerifier.AssertEitherExtModelAttribute(typeInfo); var list = new List <MemberInfo>(); foreach (var mi in typeInfo.GetMembers(BindingFlags.Public | BindingFlags.Instance)) { if ((mi.MemberType == MemberTypes.Property && ReflectionUtil.TryGetSetter(mi) != null) || mi.MemberType == MemberTypes.Field) { if (mi.DeclaringType != null && !mi.DeclaringType.GetTypeInfo().IsAssignableFrom(typeof(RdReflectionBindableBase))) { list.Add(mi); } } } return(list.ToArray()); }
private object ActivateRdExtMember(MemberInfo mi) { var returnType = ReflectionUtil.GetReturnType(mi); var typeInfo = returnType.GetTypeInfo(); var implementingType = ReflectionSerializerVerifier.GetImplementingType(typeInfo); object result; if (implementingType.GetTypeInfo().IsGenericType) { result = ActivateGenericMember(mi.Name, typeInfo); } else { result = ActivateRd(returnType); } SetAsync(mi, result); return(result); }
private object ActivateRd(Type type) { #if JET_MODE_ASSERT Assertion.Assert(!myCurrentActivationChain.Contains(type), $"Unable to activate {type.FullName}: circular dependency detected: {string.Join(" -> ", myCurrentActivationChain.Select(t => t.FullName).ToArray())}"); myCurrentActivationChain.Enqueue(type); #endif var typeInfo = type.GetTypeInfo(); ReflectionSerializerVerifier.AssertValidRdExt(typeInfo); var implementingType = ReflectionSerializerVerifier.GetImplementingType(typeInfo); Assertion.Assert(typeof(IRdBindable).GetTypeInfo().IsAssignableFrom(implementingType), $"Unable to activate {type.FullName}: type should be {nameof(IRdBindable)}"); var instance = Activator.CreateInstance(implementingType); var implementingTypeInfo = implementingType.GetTypeInfo(); foreach (var mi in ReflectionSerializers.GetBindableMembers(implementingTypeInfo)) { ReflectionSerializerVerifier.AssertMemberDeclaration(mi); var currentValue = ReflectionUtil.GetGetter(mi)(instance); if (currentValue == null) { currentValue = ActivateRdExtMember(mi); var memberSetter = ReflectionUtil.GetSetter(mi); memberSetter(instance, currentValue); } } #if JET_MODE_ASSERT myCurrentActivationChain.Dequeue(); #endif // Allow initialize to setup bindings to composite properties. if (instance is RdReflectionBindableBase reflectionBindable) { reflectionBindable.OnActivated(); } return(instance); }
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); }
private SerializerPair GetPrimitiveSerializer <T>() { Assertion.Assert(ReflectionSerializerVerifier.IsPrimitive(typeof(T)), $"{typeof(T).ToString(true)} expected to be primitive type"); return(mySerializers[typeof(T)]); }
private object ReflectionInitInternal(object instance) { var typeInfo = instance.GetType().GetTypeInfo(); if (ReflectionSerializerVerifier.HasRdExtAttribute(instance.GetType().GetTypeInfo())) { ReflectionSerializerVerifier.AssertValidRdExt(typeInfo); } foreach (var mi in SerializerReflectionUtil.GetBindableMembers(typeInfo)) { ReflectionSerializerVerifier.AssertMemberDeclaration(mi); var currentValue = ReflectionUtil.GetGetter(mi)(instance); if (currentValue == null) { currentValue = ActivateRdExtMember(mi); var memberSetter = ReflectionUtil.GetSetter(mi); memberSetter(instance, currentValue); } else { var implementingType = ReflectionSerializerVerifier.GetImplementingType(ReflectionUtil.GetReturnType(mi).GetTypeInfo()); Assertion.Assert(currentValue.GetType() == implementingType, "Bindable field {0} was initialized with incompatible type. Expected type {1}, actual {2}", mi, implementingType.ToString(true), currentValue.GetType().ToString(true)); } } // Add RdEndpoint for Impl class (counterpart of Proxy) var interfaces = typeInfo.GetInterfaces(); bool isProxy = interfaces.Contains(typeof(IProxyTypeMarker)); var rpcInterface = ReflectionSerializersFactory.GetRpcInterface(typeInfo); if (!isProxy && rpcInterface != null) { var bindableChildren = ((IReflectionBindable)instance).BindableChildren; var interfaceMap = typeInfo.GetInterfaceMap(rpcInterface); var interfaceMethods = interfaceMap.InterfaceMethods; // Dynamic adapters for Properties are not required, so skip them var ignoreMethods = new HashSet <string>(StringComparer.Ordinal); foreach (var propertyInfo in rpcInterface.GetProperties(BindingFlags.Instance | BindingFlags.Public)) { ignoreMethods.Add(propertyInfo.GetSetMethod()?.Name); ignoreMethods.Add(propertyInfo.GetGetMethod()?.Name); } foreach (var interfaceMethod in interfaceMethods) { if (ignoreMethods.Contains(interfaceMethod.Name)) { continue; } var adapter = myProxyGenerator.CreateAdapter(rpcInterface, interfaceMethod); var name = ProxyGenerator.ProxyFieldName(interfaceMethod); var requestType = ProxyGenerator.GetRequstType(interfaceMethod)[0]; EnsureFakeTupleRegistered(requestType); var responseNonTaskType = ProxyGenerator.GetResponseType(interfaceMethod, unwrapTask: true); var responseType = ProxyGenerator.GetResponseType(interfaceMethod, unwrapTask: false); var endPointType = typeof(RdCall <,>).MakeGenericType(requestType, responseNonTaskType); var endpoint = ActivateGenericMember(name, endPointType.GetTypeInfo()); SetAsync(interfaceMethod, endpoint); if (endpoint is RdReactiveBase reactiveBase) { reactiveBase.ValueCanBeNull = true; } if (ProxyGenerator.IsSync(interfaceMethod)) { var delType = typeof(Func <, ,>).MakeGenericType(typeof(Lifetime), requestType, typeof(RdTask <>).MakeGenericType(responseNonTaskType)); var @delegate = adapter.CreateDelegate(delType, instance); var methodInfo = typeof(ReflectionRdActivator).GetMethod(nameof(SetHandler)).NotNull().MakeGenericMethod(requestType, responseNonTaskType); methodInfo.Invoke(null, new[] { endpoint, @delegate }); } else { if (responseType == typeof(Task)) { var delType = typeof(Func <, ,>).MakeGenericType(typeof(Lifetime), requestType, typeof(Task)); var @delegate = adapter.CreateDelegate(delType, instance); var methodInfo = typeof(ReflectionRdActivator).GetMethod(nameof(SetHandlerTaskVoid)).NotNull().MakeGenericMethod(requestType); methodInfo.Invoke(null, new[] { endpoint, @delegate }); } else { var delType = typeof(Func <, ,>).MakeGenericType(typeof(Lifetime), requestType, typeof(Task <>).MakeGenericType(responseNonTaskType)); var @delegate = adapter.CreateDelegate(delType, instance); var methodInfo = typeof(ReflectionRdActivator).GetMethod(nameof(SetHandlerTask)).NotNull().MakeGenericMethod(requestType, responseNonTaskType); methodInfo.Invoke(null, new[] { endpoint, @delegate }); } } bindableChildren.Add(new KeyValuePair <string, object>(name, endpoint)); } } else if (rpcInterface != null) { foreach (var interfaceMethod in rpcInterface.GetMethods()) { var requestType = ProxyGenerator.GetRequstType(interfaceMethod)[0]; EnsureFakeTupleRegistered(requestType); } } // Allow initialize to setup bindings to composite properties. if (instance is IReflectionBindable reflectionBindable) { reflectionBindable.OnActivated(); } return(instance); }
/// <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); }
/// <summary> /// Return static serializers for type /// </summary> /// <param name="type"></param> /// <returns></returns> public SerializerPair GetOrCreate(Type type) { if (myStaticSerializers.TryGetValue(type, out var pair)) { return(pair); } if (myBlackListChecker(type)) { Assertion.Fail($"Attempt to create serializer for black-listed type: {type.ToString(true)}"); } var result = CreateSerializer(type); myStaticSerializers[type] = result; return(result); SerializerPair CreateSerializer(Type t) { var typeInfo = t.GetTypeInfo(); var intrinsic = Intrinsic.TryGetIntrinsicSerializer(typeInfo, GetInstanceSerializer); if (intrinsic != null) { myTypesCatalog.AddType(type); return(intrinsic); } if (IsList(t)) { var genericTypeArgument = t.GetGenericArguments()[0]; var argumentTypeSerializerPair = GetInstanceSerializer(genericTypeArgument); return((SerializerPair)ReflectionUtil.InvokeStaticGeneric(typeof(CollectionSerializers), nameof(CollectionSerializers.CreateListSerializerPair), genericTypeArgument, argumentTypeSerializerPair)); } else if (IsDictionary(t) || IsReadOnlyDictionary(t)) { var typeArguments = t.GetGenericArguments(); var tkey = typeArguments[0]; var tvalue = typeArguments[1]; var keySerializer = GetInstanceSerializer(tkey); var valueSerializer = GetInstanceSerializer(tvalue); var serializersFactoryName = IsReadOnlyDictionary(t) ? nameof(CollectionSerializers.CreateReadOnlyDictionarySerializerPair) : nameof(CollectionSerializers.CreateDictionarySerializerPair); return((SerializerPair)ReflectionUtil.InvokeStaticGeneric2(typeof(CollectionSerializers), serializersFactoryName, tkey, tvalue, keySerializer, valueSerializer)); } else if (t.IsArray) { return((SerializerPair)ReflectionUtil.InvokeGenericThis(this, nameof(CreateArraySerializer), t.GetElementType())); } else if (t.IsEnum) { var serializer = ReflectionUtil.InvokeGenericThis(this, nameof(CreateEnumSerializer), t); return((SerializerPair)serializer); } else if (ReflectionSerializerVerifier.IsValueTuple(typeInfo)) { return((SerializerPair)ReflectionUtil.InvokeGenericThis(this, nameof(CreateValueTupleSerializer), type)); } else if (typeInfo.IsGenericType && typeInfo.GetGenericTypeDefinition() == typeof(Nullable <>)) { var genericTypeArgument = typeInfo.GetGenericArguments()[0]; var nullableSerializer = (SerializerPair)ReflectionUtil.InvokeGenericThis(this, nameof(RegisterNullable), genericTypeArgument); return(nullableSerializer); // return CreateGenericSerializer(member, typeInfo, implementingType, implementingTypeInfo); } else { myTypesCatalog.AddType(type); var serializer = ReflectionUtil.InvokeGenericThis(this, nameof(CreateCustomScalar), t); return((SerializerPair)serializer); } } }
public static SerializerPair TryGetIntrinsicSerializer(TypeInfo typeInfo, Func <Type, SerializerPair> getInstanceSerializer) { if (ReflectionSerializerVerifier.HasIntrinsicNonProtocolMethods(typeInfo)) { var genericArguments = typeInfo.GetGenericArguments(); /* * if (genericArguments.Length == 1) * { * var argument = genericArguments[0]; * var staticRead = SerializerReflectionUtil.GetReadStaticSerializer(typeInfo, argument); * var staticWrite = SerializerReflectionUtil.GetWriteStaticDeserializer(typeInfo); * return SerializerPair.CreateFromMethods(staticRead, staticWrite, getInstanceSerializer(argument)); * } */ if (genericArguments.Length == 0) { var staticRead = SerializerReflectionUtil.GetReadStaticNonProtocolSerializer(typeInfo); var instanceWriter = SerializerReflectionUtil.GetWriteNonProtocolDeserializer(typeInfo); return(SerializerPair.CreateFromNonProtocolMethods(staticRead, instanceWriter)); } return(null); } if (ReflectionSerializerVerifier.HasIntrinsicProtocolMethods(typeInfo)) { var genericArguments = typeInfo.GetGenericArguments(); if (genericArguments.Length == 1) { var argument = genericArguments[0]; var staticRead = SerializerReflectionUtil.GetReadStaticSerializer(typeInfo, argument); var staticWrite = SerializerReflectionUtil.GetWriteStaticDeserializer(typeInfo); return(SerializerPair.CreateFromMethods(staticRead, staticWrite, getInstanceSerializer(argument))); } if (genericArguments.Length == 0) { var staticRead = SerializerReflectionUtil.GetReadStaticSerializer(typeInfo); var staticWrite = SerializerReflectionUtil.GetWriteStaticDeserializer(typeInfo); return(SerializerPair.CreateFromMethods(staticRead, staticWrite)); } return(null); } else if (ReflectionSerializerVerifier.HasIntrinsicFields(typeInfo)) { var readField = typeInfo.GetField("Read", BindingFlags.Public | BindingFlags.Static); var writeField = typeInfo.GetField("Write", BindingFlags.Public | BindingFlags.Static); if (readField == null) { Assertion.Fail($"Invalid intrinsic serializer for type {typeInfo}. Static field 'Read' with type {typeof(CtxReadDelegate<>).ToString(true)} not found"); } if (writeField == null) { Assertion.Fail($"Invalid intrinsic serializer for type {typeInfo}. Static field 'Write' with type {typeof(CtxWriteDelegate<>).ToString(true)} not found"); } var reader = readField.GetValue(null); var writer = writeField.GetValue(null); return(new SerializerPair(reader, writer)); } else if (ReflectionSerializerVerifier.HasIntrinsicAttribute(typeInfo)) { var marshallerType = typeInfo.GetCustomAttribute <RdScalarAttribute>().NotNull().Marshaller; var marshaller = Activator.CreateInstance(marshallerType); return((SerializerPair)ReflectionUtil.InvokeStaticGeneric(typeof(SerializerPair), nameof(SerializerPair.FromMarshaller), typeInfo, marshaller)); } return(null); }