Export to GitHub

linfu - issue #36

DynamicProxy: Problem with generic constraints


Posted on Sep 17, 2009 by Happy Cat

When i try to create a proxy for the following (test) interface:

public interface ITestInterface<P> where P : struct { T GetIdentity<T>(T obj) where T : ITestInterface<P>; }

I get the following exception:

System.Security.VerificationException: Method ITestInterface`1[System.Int32].GetIdentity: type argument 'T' violates the constraint of type parameter 'T'.

When i remove the generic constraints, i get the following exception:

System.InvalidOperationException: Late bound operations cannot be performed on types or methods for which ContainsGenericParameters is true.

Does LinFu have problems with generic methods in general?

Comment #1

Posted on Sep 17, 2009 by Massive Bird

Hi Rauhotz,

LinFu.DP1 doesn't have problems with generic methods. Did you try to proxy the ITestInterface

without specifying what P should be?

Comment #2

Posted on Sep 17, 2009 by Happy Cat

Hi, it looks like the problem only appears when run from an NUnit unit test:

[TestFixture] public class LinFuTest { public interface ITestInterface

where P : struct { T GetIdentity(T obj) where T : ITestInterface

; }

    public class TestInterfaceImpl<P> : ITestInterface<P> where P : struct
    {
        public T GetIdentity<T>(T obj) where T : ITestInterface<P>
        {
            return obj;
        }
    }

    public class ProxyFactory
    {
        public class InterceptorWrapper : LinFu.DynamicProxy.IInterceptor
        {
            private readonly IInterceptor interceptor;

            public InterceptorWrapper(IInterceptor interceptor)
            {
                this.interceptor = interceptor;
            }

            public object Intercept(LinFu.DynamicProxy.InvocationInfo info)
            {
                return this.interceptor.Intercept(
                    new InvocationInfo(info.Target,
                                       info.TargetMethod,
                                       info.StackTrace,
                                       info.TypeArguments,
                                       info.Arguments)
                    );
            }
        }

        public static ProxyFactory Default = new ProxyFactory();

        private readonly LinFu.DynamicProxy.ProxyFactory factory = new

LinFu.DynamicProxy.ProxyFactory();

        public T CreateProxy<T>(IInterceptor interceptor)
        {
            return (T)this.factory.CreateProxy(typeof(object), new

InterceptorWrapper(interceptor), typeof(T)); }

        public object CreateProxy(Type instanceType, IInterceptor interceptor)
        {
            return this.factory.CreateProxy<object>(new

InterceptorWrapper(interceptor), instanceType); } }

    public static class LockingProxy
    {
        /// <summary>
        /// Creates a proxy for an object that locks all calls to the
        /// object by the object itself as semaphore.
        /// </summary>
        public static T Create<T>(object target)
        {
            var interceptor = new LockingInterceptor(target);
            return ProxyFactory.Default.CreateProxy<T>(interceptor);
        }

        public static T Create<T>(T target)
        {
            var interceptor = new LockingInterceptor(target);
            return ProxyFactory.Default.CreateProxy<T>(interceptor);
        }
    }

    public class LockingInterceptor : IInterceptor
    {
        private readonly object target;

        public LockingInterceptor(object target)
        {
            if (target == null) throw new ArgumentNullException("target");

            this.target = target;
        }

        #region IInterceptor Members

        public object Intercept(InvocationInfo info)
        {
            lock (target)
            {
                try
                {
                    return info.TargetMethod.Invoke(target, info.Arguments);
                }
                catch (Exception ex)
                {
                    throw ex.InnerException ?? ex;
                }
            }
        }

        #endregion
    }

    [Test]
    public void Test()
    {
        var obj = new TestInterfaceImpl<int>();
        Assert.AreEqual(obj, obj.GetIdentity(obj));
        var proxy = LockingProxy.Create<ITestInterface<int>>(obj);
        Assert.AreEqual(obj, proxy.GetIdentity(obj));
    }
}

Status: New

Labels:
Type-Defect Priority-Medium