C# 如何获取带参数的Ctor的ConstructorInfo

C# 如何获取带参数的Ctor的ConstructorInfo,c#,reflection,constructor,system.reflection,system.type,C#,Reflection,Constructor,System.reflection,System.type,我正在尝试编写接收参数列表并获取匹配的构造函数信息的代码 方法签名是ConstructorInfo GetConstructorInfo(类型,对象[]args) 我创建了一个类来处理: public class ClassWithParamsInCtor { public ClassWithParamsInCtor(params int[] parameters) { } } 使用Activatorclass I可以创建此对象的实例: ClassWithParams

我正在尝试编写接收参数列表并获取匹配的构造函数信息的代码

方法签名是
ConstructorInfo GetConstructorInfo(类型,对象[]args)

我创建了一个类来处理:

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

    }
}
使用
Activator
class I可以创建此对象的实例:

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

试试这个

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

希望有帮助,

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


如果我理解正确,我想我有办法解决你的问题

假设您拥有以下类别:

 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);
        }
public static bool HaveSameItems(此IEnumerable a,IEnumerable b)
{
var dictionary=a.GroupBy(x=>x).ToDictionary(g=>g.Key,g=>g.Count());
foreach(b中的var项目)
{
int值;
if(!dictionary.TryGetValue(项,输出值))
{
返回false;
}
如果(值==0)
{
返回false;
}
字典[项目]-=1;
}
返回dictionary.All(x=>x.Value==0);
}

我很确定单元测试可以实现得更细粒度,但考虑到这是概念证明,我觉得它们很不错。

谢谢Berkay!这很有帮助,但当这不是ctor的唯一参数时,仍然存在一个问题。例如,如果Ctor得到一个双x和参数int[]args,并且我的方法被传递了一个对象[],该对象为[3.5,1,2]。如果参数类型为int,我可以开始贪婪地匹配参数,但我希望有更好的方法谢谢Selman!这在上述情况下确实有帮助,但我仍然有一个问题。我已经在给Berkay的评论中详细解释了这个问题,我将不胜感激help@Belgi当ur方法采用
double
params int[]
使用
新类型[]{typeof(double),typeof(int[])}
时,问题是我事先不知道如何解构我接收的对象[],这是一段通用代码,用于调用不同的types@Belgi嗯,在这种情况下,您可以试着获取类型数组:
args.Select(x=>x.GetType()).ToArray()
并将其传递给
GetConstructor
,但这对params ofc不起作用。当您传递两个整数时,它将返回两个
typeof(int)
,您需要专门处理参数,因为参数列表末尾定义了参数,请检查参数末尾是否包含相同类型的参数,例如如果它是
double,string,int,int,int
,您可以检查是否有接受double的构造函数,字符串和int[]数组
 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);
        }