Example #1
0
        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);
        }