如何在只有一个“对象”的情况下从通用派生类实例中检索静态属性?

时间:2014-02-11 16:46:01

标签: c# generics inheritance reflection

我有一个源自通用基础的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

我接受了Sacrilege解决方案,因为他解决了我最大的问题。我也认为根本不可能做我正在尝试的事情。但是不要试图让它有效,因为它没有。我无法从我使用的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
            }

2 个答案:

答案 0 :(得分: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);

答案 1 :(得分:0)

以前的答案还可以,但有默认值。返回的对象并不完全是预期的对象(似乎是它的副本)。我认为密钥位于标志中:&#34; FlattenHierarchy&#34;。

以下代码完美运行:

    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;