unitycontainer / interception

Unity.Interception package
Apache License 2.0
22 stars 17 forks source link

Unable to use InterfaceInterception with Covariant / Contravariant Interfaces #5

Closed ENikS closed 6 years ago

ENikS commented 6 years ago

@japrom wrote:

I have a pretty trivial example using latest on NuGet (Unity / Unity.Interception 4.0.1)

public interface IInterface<in TIn, out TOut>
{
  TOut DoSomething(TIn input);
}

public class Thing : IInterface<string, string>
{
  public string DoSomething(string input)
  {
    return input;
  }
}

public class TestInterceptor : IInterceptionBehavior
{
    public bool WillExecute => true;

    public IEnumerable<Type> GetRequiredInterfaces()
    {
        return Type.EmptyTypes;
    }

    public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
    {
        return getNext()(input, null);
    }
}

public void Main(string[] args)
{
    var proxy = Intercept.ThroughProxy<IInterface<string, string>>(
      new Thing(),
      new InterfaceInterceptor(),
      new[] { new TestInterceptor() });

    proxy.DoSomething("hello world");
}

Results in the exception:

TypeLoadException: Could not load type 'DynamicModule.ns.Wrapped_IInterface`2_f77b7d7f16c54c3393a389eedeced496' from assembly 'Unity_ILEmit_InterfaceProxies, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' because it declares a covariant or contravariant type parameter and is not an interface or delegate.

I dug into the code a bit and found InterfaceInterceptorClassGenerator.cs.

Zeroing the *variant flags seems to make it work for me.

genericTypes[i].SetGenericParameterAttributes(
  genericArguments[i].GenericParameterAttributes & ~GenericParameterAttributes.VarianceMask
);

Is there any reason why they should be there?

ENikS commented 6 years ago

Fixed in 52fb1fb733a09385cc53387084ef29153c398a4f