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 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 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}"); }
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}"); }
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 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); }
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 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); }