private object ReflectionInitInternal()

in rd-net/RdFramework.Reflection/ReflectionRdActivator.cs [172:273]


    private object ReflectionInitInternal(object instance)
    {
      var typeInfo = instance.GetType().GetTypeInfo();

      if (ReflectionSerializerVerifier.HasRdExtAttribute(instance.GetType().GetTypeInfo()))
        ReflectionSerializerVerifier.AssertValidRdExt(typeInfo);

      foreach (var mi in SerializerReflectionUtil.GetSerializableFields(typeInfo))
      {
        var currentValue = ReflectionUtil.GetGetter(mi)(instance);
        if (currentValue == null)
        {
          currentValue = ActivateMember(ReflectionUtil.GetReturnType(mi), mi.Name);
          var memberSetter = ReflectionUtil.GetSetter(mi);
          memberSetter(instance, currentValue);
        }
        else
        {
          var implementingType = ReflectionSerializerVerifier.GetImplementingType(ReflectionUtil.GetReturnType(mi).GetTypeInfo());
          if (Mode.IsAssertion) 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 = ReflectionSerializerVerifier.GetRpcInterface(typeInfo);

      if (!isProxy && rpcInterface != null)
      {
        var interfaceMethods = ReflectionSerializerVerifier.GetMethodsMap(typeInfo, rpcInterface);

        foreach (var interfaceMethod in interfaceMethods)
        {
          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()).NotNull();
          SetAsync(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});
            }
          }
          var bindableChildren = ((IReflectionBindable)instance).BindableChildren;
          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.EnsureBindableChildren();
        if (reflectionBindable.BindableChildren.Count == 0)
        {
          ourLog.Warn($"{reflectionBindable.GetType().ToString(true)} RdExt without bindable children was activated.");
        }

        reflectionBindable.OnActivated();
      }

      return instance;
    }