ekonbenefits / impromptu-interface

Static interface to dynamic implementation (duck casting). Uses the DLR combined with Reflect.Emit.
Apache License 2.0
656 stars 67 forks source link

ActLike interface with default implementation produces exception #42

Closed teneko closed 3 years ago

teneko commented 3 years ago

I am getting an exception when using an interface that contains default implementations.

public interface IJSObjectReferenceFacade
    {
        IJSObjectReference JSObjectReference { get; }

        bool TryInvokeAsync<TValue>(string identifier, object?[] args, out ValueTask<TValue> result)
        {
            result = default;
            return false;
        }

        ValueTask<TValue> InvokeAsync<TValue>(string identifier, params object?[] args)
        {
            if (TryInvokeAsync<TValue>(identifier, args, out var result)) {
                return result;
            }

            return JSFunctionalObjectReference.Default.InvokeAsync<TValue>(JSObjectReference, identifier, args);
        }

        ValueTask<TValue> InvokeAsync<TValue>(string identifier, CancellationToken cancellationToken, params object?[] args)
        {
            if (TryInvokeAsync<TValue>(identifier, args, out var result)) {
                return result;
            }

            return JSFunctionalObjectReference.Default.InvokeAsync<TValue>(JSObjectReference, identifier, cancellationToken, args);
        }

        ValueTask<TValue> InvokeAsync<TValue>(string identifier, TimeSpan timeout, params object?[] args)
        {
            if (TryInvokeAsync<TValue>(identifier, args, out var result)) {
                return result;
            }

            return JSFunctionalObjectReference.Default.InvokeAsync<TValue>(JSObjectReference, identifier, timeout, args);
        }

        bool TryInvokeVoidAsync(string identifier, object?[] args, out ValueTask result)
        {
            result = default;
            return false;
        }

        ValueTask InvokeVoidAsync(string identifier, params object?[] args)
        {
            if (TryInvokeVoidAsync(identifier, args, out var result)) {
                return result;
            }

            return JSFunctionalObjectReference.Default.InvokeVoidAsync(JSObjectReference, identifier, args);
        }

        ValueTask InvokeVoidAsync(string identifier, CancellationToken cancellationToken, params object?[] args)
        {
            if (TryInvokeVoidAsync(identifier, args, out var result)) {
                return result;
            }

            return JSFunctionalObjectReference.Default.InvokeVoidAsync(JSObjectReference, identifier, cancellationToken, args);
        }

        ValueTask InvokeVoidAsync(string identifier, TimeSpan timeout, params object?[] args)
        {
            if (TryInvokeVoidAsync(identifier, args, out var result)) {
                return result;
            }

            return JSFunctionalObjectReference.Default.InvokeVoidAsync(JSObjectReference, identifier, timeout, args);
        }
    }

...

return jsDynamicObject.ActLike<IJSObjectReferenceFacade>(new DynamicObject()); // error

Here the stacktrace:

Nachricht: 
    System.ArgumentException : The number of generic arguments provided doesn't equal the arity of the generic type definition. (Parameter 'instantiation')
  Stapelüberwachung: 
    RuntimeType.MakeGenericType(Type[] instantiation)
    BuildProxy.UpdateCallsiteFuncType(Type tFuncGeneric, Type returnType, Type[] argTypes)
    BuildProxy.MakeMethod(ModuleBuilder builder, MethodInfo info, TypeBuilder typeBuilder, Type contextType, Boolean nonRecursive, Boolean defaultImp)
    BuildProxy.BuildTypeHelper(ModuleBuilder builder, Type contextType, Type[] interfaces)
    BuildProxy.BuildType(Type contextType, Type mainInterface, Type[] otherInterfaces)
    Impromptu.ActLike[TInterface](Object originalDynamic, Type[] otherInterfaces)
    JSDynamicObjectActivator.CreateInstance[T](IJSObjectReference jsObjectReference) Zeile 55
    JSDynamicObjectTests.Should_expect_identifier_as_passed() Zeile 37
    --- End of stack trace from previous location ---

I tried to look in BuildProxy.cs but I cannot effort the time currently to understand 2000 lines of code.