For anyone who wants it, figure this is a commonly wanted thing. If anything
is wrong would love to know as well :)

    public static class ParameterDefinitionExtensions
    {
        public static TypeReference GetTypeWithGenericResolve(this
ParameterDefinition definition)
        {
            return GetTypeWithGenericResolve(definition, null);
        }

        public static TypeReference GetTypeWithGenericResolve(this
ParameterDefinition definition, GenericInstanceMethod genericInstanceMethod)
        {
            var ret = definition.ParameterType;
            if (definition.ParameterType.IsGenericParameter)
            {
                var f = (MethodReference)definition.Method;
                if (f.DeclaringType is GenericInstanceType)
                {
                    var position =

 
((GenericInstanceType)f.DeclaringType).ElementType.GenericParameters.GetIndexByName(
                            definition.ParameterType.Name);
                    if (position != -1)
                        ret =
((GenericInstanceType)f.DeclaringType).GenericArguments[position];
                }
                if (genericInstanceMethod != null)
                {
                    var position =

 f.GetElementMethod().GenericParameters.GetIndexByName(
definition.ParameterType.Name);
                    if (position != -1)
                        ret =
genericInstanceMethod.GenericArguments[position];
                }
            }
            return ret;
        }

Tests:

using AssemblyChangeDetector;
using AssemblyChangeDetector.Extensions;
using Mono.Cecil;
using NUnit.Framework;

namespace Coupling.Tests
{
    [TestFixture]
    public class when_translating_parameters : AssemblyTestFixture
    {
        [Test]
        public void non_generic_parameter_translates_to_itself()
        {
            var method =
assembly.GetMethodDefinition<ParameterTestMethods>("NonGenericCall");
            var references =
TypeScanner.MemberReferenceDependenciesForMethod(method);
            var type =
references[0].ActualMethodDefinition.Parameters[0].GetTypeWithGenericResolve();
            Assert.That(type ==
references[0].ActualMethodDefinition.Parameters[0].ParameterType);
        }

        [Test]
        public void
closed_generic_parameter_translates_to_generic_argument_on_static()
        {
            var method =
assembly.GetMethodDefinition<ParameterTestMethods>("ClosedStaticGenericCall");
            var references =
TypeScanner.MemberReferenceDependenciesForMethod(method);
            var type =
references[0].ActualMethodDefinition.Parameters[0].GetTypeWithGenericResolve();
            Assert.That(type.FullName == "System.Int32");
        }


        [Test]
        public void
closed_generic_parameter_translates_to_generic_argument_on_instance()
        {
            var method =
assembly.GetMethodDefinition<ParameterTestMethods>("ClosedInstanceGenericCall");
            var references =
TypeScanner.MemberReferenceDependenciesForMethod(method);
            var type =
references[1].ActualMethodDefinition.Parameters[0].GetTypeWithGenericResolve();
            Assert.AreEqual(type.FullName,"System.String");
        }

        [Test]
        public void generic_parameter_on_static_method_can_be_translated()
        {
            var method =
assembly.GetMethodDefinition<ParameterTestMethods>("StaticWithGenericParameter");
            var references =
TypeScanner.MemberReferenceDependenciesForMethod(method);
            var testReference =
(GenericInstanceMethod)references[0].ActualMethodDefinition;
            var type =
testReference.Parameters[0].GetTypeWithGenericResolve(testReference);
            Assert.That(type.FullName == "System.String");
        }

        [Test]
        public void generic_argument_and_generic_parameter_on_static()
        {
            var method =
assembly.GetMethodDefinition<ParameterTestMethods>("ClosedStaticWithGenericParameter");
            var references =
TypeScanner.MemberReferenceDependenciesForMethod(method);
            var testReference = (GenericInstanceMethod)
references[0].ActualMethodDefinition;
            var type =
testReference.Parameters[0].GetTypeWithGenericResolve( testReference);
            Assert.That(type.FullName == "System.String");
            type =
testReference.Parameters[1].GetTypeWithGenericResolve(testReference);
            Assert.That(type.FullName == "System.Int32");
        }

        [Test]
        public void can_read_array_type_argument()
        {
            var method =
assembly.GetMethodDefinition<ParameterTestMethods>("ClosedInstanceTypeSpecGenericCall");
            var references =
TypeScanner.MemberReferenceDependenciesForMethod(method);
            var type =
references[1].ActualMethodDefinition.Parameters[0].GetTypeWithGenericResolve();
            Assert.AreEqual(type.FullName, "System.String[]");

        }

        [Test]
        public void can_read_array_type_parameter()
        {
            var method =
assembly.GetMethodDefinition<ParameterTestMethods>("StaticWithTypeSpecGenericParameter");
            var references =
TypeScanner.MemberReferenceDependenciesForMethod(method);
            var testReference =
(GenericInstanceMethod)references[1].ActualMethodDefinition;
            var type =
testReference.Parameters[0].GetTypeWithGenericResolve(testReference);
            Assert.AreEqual(type.FullName,"System.String[]");
        }

        [Test]
        public void can_read_open_generic_type_argument_with_translation()
        {
            var method =
assembly.GetMethodDefinition(typeof(OpenParameterTestMethods<>),
"OpenInstanceGenericCall");
            var references =
TypeScanner.MemberReferenceDependenciesForMethod(method);
            var type =
references[2].ActualMethodDefinition.Parameters[0].GetTypeWithGenericResolve();
            Assert.AreEqual(type.FullName, "TFoo");
        }

        [Test]
        public void can_read_open_generic_parameter_with_translation()
        {
            var method =
assembly.GetMethodDefinition(typeof(OpenParameterTestMethods<>),
"OpenParameterGenericCall");
            var references =
TypeScanner.MemberReferenceDependenciesForMethod(method);
            var type =
references[1].ActualMethodDefinition.Parameters[0].GetTypeWithGenericResolve();
            Assert.AreEqual(type.FullName, "TFoo");
        }
    }

    public class ParameterTestMethods
    {
        private static void Call(int x)
        {

        }

        private static void Whatever<T>(T val) {}

        public void StaticWithGenericParameter()
        {
            Whatever<string>("hello");
        }

        public void StaticWithTypeSpecGenericParameter()
        {
            Whatever<string[]>(new[] {"hello"});
        }

        public void ClosedStaticWithGenericParameter()
        {
            GenericStatic<int>.WithParam<string>("hello", 42);
        }

        public void ClosedInstanceTypeSpecGenericCall()
        {
            GenericStatic<string[]>.Something(new []{"hello"});
        }

        public void ClosedInstanceGenericCall()
        {
            new InstanceGenericClass<int, string>().Something("test");
        }
        public void ClosedStaticGenericCall()
        {
            GenericStatic<int>.Something(5);
        }
        public void NonGenericCall()
        {
            Call(42);
        }
    }

    class OpenParameterTestMethods<TFoo>
    {
        public void OpenInstanceGenericCall()
        {
            new SimpleGenericClass<TFoo>().Foo(default(TFoo));
        }

        public void OpenParameterGenericCall()
        {
            GenericStatic<TFoo>.Something(default(TFoo));
        }
    }

    static class GenericStatic<T>
    {
        public static void WithParam<V>(V val, T val2)
        {

        }
        public static void Something(T val)
        {

        }
    }

    class InstanceGenericClass<T,V>
    {
        public void Something(V val)
        {

        }
    }

}


-- 
Les erreurs de grammaire et de syntaxe ont été incluses pour m'assurer de
votre attention

-- 
--
mono-cecil

Reply via email to