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