impromptu-interface icon indicating copy to clipboard operation
impromptu-interface copied to clipboard

ActLike() fails with explicit interface implementation

Open piedar opened this issue 4 years ago • 2 comments

I'm not sure if this is expected behavior.

interface IDo
{
    void Do();
}

sealed class DoNothing : IDo
{
    void IDo.Do() { }
}
class TheDoNothing
{
    [Test]
    public void CanActLike()
    {
        var instance = new DoNothing();
        var acting = instance.ActLike<IDo>();
        acting.Do(); // throws RuntimeBinderException
    }
}

I read about Dynamitey UsagePrivate but this produces the same result.

class TheDoNothing
{
    [Test]
    public void CanActLike()
    {
        var instance = new DoNothing();
        var context = new InvokeContext(instance, typeof(IDo));
        var acting = context.ActLike<IDo>();
        acting.Do(); // throws RuntimeBinderException
    }
}

Obviously this a toy example, but I'm running into real issues when trying to do something similar using DynamicActLike() with an interface type known only at runtime.

piedar avatar Apr 20 '20 17:04 piedar

Yeah, with this toy example, I'd just test to see if instance already implements IDo and not run ActLike.

If it's not the same interface, explicit interfaces are very tricky, because the methods names are all qualified. How do I know what the name of the interface you are intending, I'd have do an exhaustive search with reflection,

jbtule avatar Apr 20 '20 19:04 jbtule

My use case is to make an instance loaded from one AssemblyLoadContext act like an interface loaded from a different AssemblyLoadContext. It is the same interface by name, but technically a different Type because it comes from a different load context. This looks something like

// find a matching Type from the assemblies loaded with the Provider's AssemblyLoadContext
Type resolvedType = ResolveType(serviceType);
object resolvedService = Provider.GetService(resolvedType);
var result = ImpromptuInterface.Impromptu.DynamicActLike(resolvedService, serviceType);

This almost works great, except that when the serviceType is Microsoft.Extensions.Logging.Abstractions.ILogger<T> the Provider produces a Logger<T> which has explicit implementations of the interface methods.

piedar avatar Apr 20 '20 19:04 piedar