2014-02-11 18 views
3

我有一個WPF控件是從一個通用的基礎派生。 例如:來自UpDownBase的NumericUpDown的來自CommonNumericUpDown的IntegerUpDown。如何在只有一個「對象」的情況下從泛型派生類實例中檢索靜態屬性?

UpDownBase具有靜態屬性聲明爲:

public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(T), typeof(UpDownBase<T>), new FrameworkPropertyMetadata(default(T), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnValueChanged, OnCoerceValue, false, UpdateSourceTrigger.LostFocus)); 

我收到以下異常: TypeLoadException(GenericArguments [0], 'System.Nullable 1[T]', on 'System.Nullable 1 [T]' 違反類型參數的約束' T」)
當我嘗試(異常發生時,‘動態’是試圖讓‘ValueProperty’):

var frameWorkElement = e.OriginalSource as FrameworkElement; 
while (frameWorkElement != null) 
{ 
    if (IsSubclassOfRawGeneric(typeof(UpDownBase<>), frameWorkElement.GetType())) // JaredPar StackOverfLow code 
    { 
     dynamic upDownT = frameWorkElement; 
     DependencyProperty dp = upDownT.ValueProperty; // TypeLoadException 
     if (dp != null) 
     { 
      be = frameWorkElement.GetBindingExpression(dp); 

      if (be != null) 
      { 
       be.UpdateSource(); 
      } 
     } 
     break; 
    } 

    frameWorkElement = VisualTreeHelper.GetParent(frameWorkElement) as FrameworkElement; 
} 

爲什麼我收到異常以及如何ç我以通用的方式從我的對象中獲取適當的dependencyProperty(沒有切換案例或類似的)?

更新

我修改JaredPar代碼來獲取類型:

private static Type GetGenericBaseTypeOfType(Type generic, Type toCheck) 
    { 
     while (toCheck != null && toCheck != typeof(object)) 
     { 
      var cur = toCheck.IsGenericType ? toCheck.GetGenericTypeDefinition() : toCheck; 
      if (generic == cur) 
      { 
       return generic; 
      } 
      toCheck = toCheck.BaseType; 
     } 
     return null; 
    } 

不過,我仍然不能得到的PropertyInfo查詢其價值。

Type genericbaseType = GetGenericBaseTypeOfType(typeof (UpDownBase<>), frameWorkElement.GetType()); // JaredPar StackOverfLow code 
           { 
            if (genericbaseType != null) 
            { 
             //UpDownBase<int>.ValueProperty ok 
// pi3 is null 
             PropertyInfo pi3 = frameWorkElement.GetType().GetProperty("ValueProperty", BindingFlags.Static | BindingFlags.FlattenHierarchy | BindingFlags.Public); 
// pi is null  
             PropertyInfo pi = genericbaseType.GetProperty("ValueProperty", BindingFlags.Static | BindingFlags.Public); 

更新2

我接受瀆聖解決方案,因爲他解決了我最大的問題。我也認爲做我想做的事根本是不可能的。但不要試圖讓它工作,因爲它不。我無法從從maked GenericType,而且從任何普通的我覺得拿到的DependencyProperty的綁定表達式,請參閱下面的代碼和註釋:

Type upDownType = typeof(UpDownBase<>).MakeGenericType(frameWorkElement.GetType().BaseType.GenericTypeArguments[0]); 

    FieldInfo fi = upDownType.GetField("ValueProperty"); 
    if (fi != null) 
    { 
     var dp = fi.GetValue(null) as DependencyProperty; 
     if (dp != null) 
     { 
      be = frameWorkElement.GetBindingExpression(dp); // Null 
      if (be != null) 
      { 
       be.UpdateSource(); 
      } 
      else 
      { 
// Next line be= null 
       be = frameWorkElement.GetBindingExpression(UpDownBase<int>.ValueProperty); // Null 
// Next line be = correct binding expression 
       be = frameWorkElement.GetBindingExpression(IntegerUpDown.ValueProperty); // Ok valid bindingExpression 
      } 
+0

哪裏例外是從哪裏來的? – SLaks

+0

嗨SLaks,它是寫在代碼評論。我會更新我的問題以更準確。謝謝! –

+0

什麼是堆棧跟蹤? – SLaks

回答

0

以前的答案是好的,但有一個默認值。返回的對象並不完全是預期的(似乎是它的副本)。我認爲關鍵在於旗幟:「FlattenHierarchy」。

下面的代碼可以正常使用:

var frameWorkElement = e.OriginalSource as FrameworkElement; 
    while (frameWorkElement != null) 
    { 
     Type genericbaseType = GetGenericBaseTypeOfType(typeof(UpDownBase<>), frameWorkElement.GetType()); // JaredPar StackOverfLow code 
     { 
      if (genericbaseType != null) 
      { 
       FieldInfo fi = frameWorkElement.GetType().GetField("ValueProperty", BindingFlags.GetField | BindingFlags.Default | BindingFlags.Public | BindingFlags.FlattenHierarchy | BindingFlags.Static | BindingFlags.SetField); 
       if (fi != null) 
       { 
        var dp = fi.GetValue(null) as DependencyProperty; 
        if (dp != null) 
        { 
         be = frameWorkElement.GetBindingExpression(dp); // Null if done like the other answer. 
         if (be != null) 
         { 
          be.UpdateSource(); 
         } 
        } 
       } 
       break; 
      } 
     } 

     frameWorkElement = VisualTreeHelper.GetParent(frameWorkElement) as FrameworkElement; 
2

您試圖在一個特定的訪問靜態屬性實例。你不能這樣做在C#中。

如果您可以安排,那麼T已知在這一點上,你可以撥打UpDownBase<T>.ValueProperty,而不是upDownT.ValueProperty。否則,你將不得不採取反思,得到T,然後也獲得財產。

此代碼應該可以在不知道T的情況下提前獲取dp值。

Type upDownType = typeof(UpDownBase<>).MakeGenericType(upDownT.GetType().BaseType.GenericTypeArguments[0]); 
DependencyProperty dp = (DependencyProperty)upDownType.GetField("ValueProperty").GetValue(null); 

參考更新3

嗯,這使得它更容易一些,然後實際。你應該能夠只得到從具體類型depedndecy屬性則是這樣的:

DependencyProperty dp = (DependencyProperty)frameWorkElement.GetType().GetField("ValueProperty").GetValue(null); 
+0

genericbaseType.GenericTypeArguments [0](從Jare​​dPar修改的代碼返回的類型:怪異類型是:「UpDownBase'1」)==>「越界數組索引」AND also:frameWorkElement .GetType()。GenericTypeArguments [0] ==>「越界數組索引」 –

+0

我沒有T或似乎是一個不同的聲明? –

+0

我修正了一件事。我最後的具體課程不是通用的。我用你的函數使用它的BaseClass,我得到了GenericType。但仍然,我無法查詢該類型的屬性被定義爲:「UpDownBase'1」??? –

相關問題