我正在尝试编写接收参数列表的代码并获取匹配的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?
答案 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);
}
我非常确定单元测试可以实现更具细节性,但考虑到这是一个概念验证,我觉得它们很不错。