public Type CreateType()

in rd-net/RdFramework.Reflection/ProxyGenerator.cs [98:167]


    public Type CreateType(Type interfaceType)
    {
      if (!interfaceType.IsInterface)
        throw new ArgumentException("Only interfaces are supported.");

      if (interfaceType.GetGenericArguments().Length > 0)
        throw new ArgumentException("Generic interfaces are not supported.");

      // RdRpc attribute can be specified in RdExt attribute. Therefore, now this assert cannot be verified.
      // if (!ReflectionSerializerVerifier.IsRpcAttributeDefined(typeof(TInterface)))
      //   throw new ArgumentException($"Unable to create proxy for {typeof(TInterface)}. No {nameof(RdRpcAttribute)} specified.");
      lock (myModuleBuilder.Value)
      {
        var moduleBuilder = myModuleBuilder.Value;
        var className = interfaceType.Name.Substring(1);
        var proxyTypeName = "Proxy." + className;
        var typebuilder = moduleBuilder.DefineType(
          proxyTypeName,
          TypeAttributes.NotPublic | TypeAttributes.Class | TypeAttributes.Sealed,
          typeof(RdExtReflectionBindableBase));

        // Implement interface
        typebuilder.AddInterfaceImplementation(interfaceType);

        // mark it as proxy type
        typebuilder.AddInterfaceImplementation(typeof(IProxyTypeMarker));

        // Add RdExt attribute to type
        var rdExtConstructor = Members.RdExtConstructor;
        typebuilder.SetCustomAttribute(new CustomAttributeBuilder(rdExtConstructor, new object[] { interfaceType }));

        var ctx = new TypeBuilderContext(typebuilder);
        ImplementInterface(interfaceType, ctx);
        foreach (var baseInterface in interfaceType.GetInterfaces())
          ImplementInterface(baseInterface, ctx);

        void ImplementInterface(Type baseInterface, TypeBuilderContext ctx)
        {
          if (baseInterface.GetCustomAttribute<RpcTimeoutAttribute>() is { } timeouts)
          {
            ctx.SetDefaultTimeout(timeouts);
          }

          foreach (var member in baseInterface.GetMembers(BindingFlags.Instance | BindingFlags.Public))
          {
            ImplementMember(ctx, member);
          }
        }

        if (ctx.TimeoutFields.IsValueCreated)
        {
          var cctor = typebuilder.DefineTypeInitializer();
          var il = cctor.GetILGenerator();
          foreach (var kvp in ctx.TimeoutFields.Value)
          {
            // Re-create RpcTimeouts attribute. It used only to re-create RpcTimeouts. It is more robust to use types for
            // ProxyGeneration which are located on our project.
            il.Emit(OpCodes.Ldc_I8, kvp.Value.WarnAwaitTime.Ticks);
            il.Emit(OpCodes.Ldc_I8, kvp.Value.ErrorAwaitTime.Ticks);
            il.Emit(OpCodes.Call, ProxyGeneratorMembers.CreateRpcTimeoutMethod);

            // set the static field
            il.Emit(OpCodes.Stsfld, kvp.Key);
          }
          il.Emit(OpCodes.Ret);
        }

        return typebuilder.CreateTypeInfo().NotNull("Unable to create type");
      }
    }