2017-04-05 26 views
1

我正在嘗試編寫接收參數列表並獲取匹配Ctor的ConstructorInfo的代碼。如何使用參數獲取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 

如何獲取C onstructorInfo在這種情況下?

回答

2

試試這個,

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

希望幫助,

+0

謝謝Berkay!這有助於解決問題,但這並不是問題的唯一論據。例如,如果Ctor獲得了double x和params int [] args,並且我的方法傳遞了[3.5,1,2]的對象[]。如果他們是int類型的,我可以貪婪地開始匹配參數,但我希望有更好的方法 – Belgi

2

params int[]int[]一個語法糖,你需要使用typeof(int[])

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

謝謝塞爾曼!這對上述情況有幫助,但我仍然有問題。我已經在我向Berkay發表的評論中更詳細地解釋了這個問題,我將不勝感激。 – Belgi

+0

@elgi方法需要'double'和'params int []'use'new Type [] {typeof(double), typeof(int [])}' –

+0

問題是,我不知道如何解構我收到的對象[],它是一個普通的代碼,旨在調用不同類型 – Belgi

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); 
     } 

我很確定單元測試可以實現更精細的特定,但考慮到這是一個概念的證明,我覺得他們體面。

相關問題