如何使用params获取Ctor的ConstructorInfo

时间:2017-04-05 14:07:42

标签: c# reflection constructor system.reflection system.type

我正在尝试编写接收参数列表的代码并获取匹配的Ctor的ConstructorInfo。

方法签名为ConstructorInfo GetConstructorInfo(Type type, object[] args)

我创建了一个可以使用的类:

public class ClassWithParamsInCtor
{
    public ClassWithParamsInCtor(params int[] parameters)
    {

    }
}

使用Activator类我可以创建此对象的实例:

ClassWithParamsInCtor myclass = Activator.CreateInstance(typeof(ClassWithParamsInCtor), new object[] { 1,2 }) as ClassWithParamsInCtor; \\returns a valid instance of the class;

但是当我尝试获取ConstructorInfo时出现问题,以下内容返回null:

ConstructorInfo ctorInfo = typeof(ClassWithParamsInCtor).GetConstructor(new Type[] { typeof(int), typeof(int) }); \\returns null

在这种情况下如何获取ConstructorInfo?

3 个答案:

答案 0 :(得分:3)

params int[]int[]的语法糖,您需要使用typeof(int[])

typeof(ClassWithParamsInCtor).GetConstructor(new Type[] { typeof(int[]) });

答案 1 :(得分:2)

试试这个,

ConstructorInfo ctorInfo = typeof(ClassWithParamsInCtor).GetConstructor(new Type[] { typeof(int[])}); 

希望有所帮助,

答案 2 :(得分:1)

如果我理解的话,我认为我有一个解决方案。

假设你有以下课程:

 public class ClassWithParamsInCtor
    {
        public ClassWithParamsInCtor(params int[] parameters)
        {

        }
        public ClassWithParamsInCtor(int[] parameters, double y)
        {

        }

        public ClassWithParamsInCtor(int[] parameters, float y)
        {

        }
    }

以下是一些单元测试,描述了我已实施的解决方案:

 [TestClass]
    public class TestClassWithParamsInCtorClass
    {
        [TestMethod]
        //Wrong data type test
        public void WrongInputDataTypesTest()
        {
            //Arrange
            var inputData = new object[] { new[] { 1, 2 }, "" };
            var inputDataTypes = inputData.Select(_ => _.GetType());

            //Act
            var matchedCtorParams = typeof(ClassWithParamsInCtor)
                                   .GetConstructors()
                                   .Select(_ => _.GetParameters().Select(a => a.ParameterType))
                                   .Where(_ => _.HaveSameItems(inputDataTypes)).ToArray();

            //Assert 
            Assert.AreEqual(null, matchedCtorParams.FirstOrDefault());
        }

        [TestMethod]
        //Test used to invoke first constructor
        public void InputDataTypesTest1()
        {
            //Arrange
            var inputData = new object[] { new[] { 1, 2 } , 1 };
            var inputDataTypes = inputData.Select(_ => _.GetType());

            //Act
            var matchedCtorParams = typeof(ClassWithParamsInCtor)
                                   .GetConstructors()
                                   .Select(_ => _.GetParameters().Select(a => a.ParameterType))
                                   .Where(_ => _.HaveSameItems(inputDataTypes)).ToArray();

           var result = typeof(ClassWithParamsInCtor).GetConstructor(matchedCtorParams.FirstOrDefault().ToArray())
                   .Invoke(inputData);

            //Assert 
            Assert.AreNotEqual(null, result);

        }

        [TestMethod]
        //Test used to invoke second constructor
        public void InputDataTypesTest2()
        {
            //Arrange
            var inputData = new object[] { new[] { 1, 2 }, 1.2 };
            var inputDataTypes = inputData.Select(_ => _.GetType());

            //Act
            var matchedCtorParams = typeof(ClassWithParamsInCtor)
                                   .GetConstructors()
                                   .Select(_ => _.GetParameters().Select(a => a.ParameterType))
                                   .Where(_ => _.HaveSameItems(inputDataTypes)).ToArray();

            var result = typeof(ClassWithParamsInCtor).GetConstructor(matchedCtorParams.FirstOrDefault().ToArray())
                    .Invoke(inputData);

            //Assert 
            Assert.AreNotEqual(null, result);

        }

        [TestMethod]
        //Test used to invoke third constructor
        public void InputDataTypesTest3()
        {
            //Arrange
            var inputData = new object[] { new[] { 1, 2 }, 3.5F };
            var inputDataTypes = inputData.Select(_ => _.GetType());

            //Act
            var matchedCtorParams = typeof(ClassWithParamsInCtor)
                                   .GetConstructors()
                                   .Select(_ => _.GetParameters().Select(a => a.ParameterType))
                                   .Where(_ => _.HaveSameItems(inputDataTypes)).ToArray();

            var result = typeof(ClassWithParamsInCtor).GetConstructor(matchedCtorParams.FirstOrDefault().ToArray())
                    .Invoke(inputData);

            //Assert 
            Assert.AreNotEqual(null, result);

        }
    }

我使用的扩展方法:

 public static bool HaveSameItems<T>(this IEnumerable<T> a, IEnumerable<T> b)
        {
            var dictionary = a.GroupBy(x => x).ToDictionary(g => g.Key, g => g.Count());
            foreach (var item in b)
            {
                int value;
                if (!dictionary.TryGetValue(item, out value))
                {
                    return false;
                }
                if (value == 0)
                {
                    return false;
                }
                dictionary[item] -= 1;
            }
            return dictionary.All(x => x.Value == 0);
        }

我非常确定单元测试可以实现更具细节性,但考虑到这是一个概念验证,我觉得它们很不错。