Как отражение говорит мне, когда свойство скрывает наследованного участника с 'новым' ключевым словом?

Обязательно используйте последнюю версию в файле build.gradle:

    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'

И определите ConstraintLayout в файлах XML как:

      <androidx.constraintlayout.widget.ConstraintLayout
       ...
       />

К сожалению, Android Jetpack инструмент работает не так хорошо, как следовало бы, и вам придется изменить код вручную.

21
задан Jon Seigel 25 April 2010 в 04:17
поделиться

4 ответа

Мы должны будем иметь дело с точки зрения методов свойства здесь, а не самого свойства, потому что это - получение/методы установки свойства, которое на самом деле переопределяется, а не само свойство. Я буду использовать получить метод, поскольку у Вас никогда не должно быть свойства без одного, хотя полное решение должно проверить из-за отсутствия одного.

Смотря на IL, испускаемый во многих случаях, 'получить' метод основного свойства будет иметь маркеры метаданных (это из компилятора C#; другие не могут испустить hidebysig в зависимости от их метода, скрывающего семантику, в этом случае, метод был бы скрытием по имени):

non-virtual : .method public hidebysig specialname instance
virtual     : .method public hidebysig specialname newslot virtual instance 

Полученный будет иметь следующие маркеры:

override    : .method public hidebysig specialname virtual instance 
new         : .method public hidebysig specialname instance
new virtual : .method public hidebysig specialname newslot virtual instance 

Таким образом, мы видим от этого, что не возможно сказать просто от маркеров метаданных метода, является ли это new потому что невиртуальный базовый метод имеет те же маркеры как невиртуальное new метод и виртуальный базовый метод имеют те же маркеры как new virtual метод.

То, что мы можем сказать, является этим, если метод имеет virtual маркер, но не newslot маркер затем это переопределяет базовый метод, а не тени это, т.е.

var prop = typeof(ChildClass).GetProperty("TempProperty");
var getMethod = prop.GetGetMethod();
if ((getMethod.Attributes & MethodAttributes.Virtual) != 0 &&
    (getMethod.Attributes & MethodAttributes.NewSlot) == 0)
{
    // the property's 'get' method is an override
}

Предположение, затем, что мы находим 'получить' метод, не является переопределением, мы хотим знать, существует ли свойство в базовом классе, что это - затенение. Проблема состоит в том, что, потому что метод находится в другом слоте таблицы метода, он на самом деле не имеет никакой непосредственной связи к методу, это - затенение. Таким образом, то, что мы на самом деле говорим, "делает базовый тип, имеют любой метод, который соответствует критериям для затенения", которое варьируется в зависимости от того, является ли метод hidebysig или скрытие по имени.

Для первого мы должны проверить, имеет ли базовый класс какой-либо метод, который соответствует подписи точно, тогда как для последнего мы должны проверить, имеет ли это любой метод с тем же именем, таким образом продолжая код сверху:

else 
{
    if (getMethod.IsHideBySig)
    {
        var flags = getMethod.IsPublic ? BindingFlags.Public : BindingFlags.NonPublic;
        flags |= getMethod.IsStatic ? BindingFlags.Static : BindingFlags.Instance;
        var paramTypes = getMethod.GetParameters().Select(p => p.ParameterType).ToArray();
        if (getMethod.DeclaringType.BaseType.GetMethod(getMethod.Name, flags, null, paramTypes, null) != null)
        {
            // the property's 'get' method shadows by signature
        }
    }
    else
    {
        var flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance;
        if (getMethod.DeclaringType.BaseType.GetMethods(flags).Any(m => m.Name == getMethod.Name))
        {
            // the property's 'get' method shadows by name
        }
    }
}

Я думаю, что это - большая часть пути там, но я все еще не думаю, что это точно правильно. Для запуска я не полностью знаком с сокрытием по имени, поскольку C# не поддерживает его, и это - в значительной степени все, что я использую, таким образом, я могу быть неправым в коде здесь, который указывает, что метод экземпляра мог тень статическая. Я также не знаю о проблеме чувствительности к регистру (например, в VB мог названный метод Foo тень названный метод foo если они оба имели ту же подпись и были обоими hidebysig - в C# ответ не, но если ответ - да в VB затем, это означает, что ответ на этот вопрос на самом деле недетерминирован).

Ну, я не уверен, сколько справки все это, кроме проиллюстрировать, что это - на самом деле намного более трудная проблема, чем я думал, что это будет (или я пропустил что-то действительно очевидное, в этом случае, я хотел бы знать!). Но надо надеяться это имеет достаточное содержание, что это помогает Вам достигнуть того, что Вы пытаетесь сделать.

23
ответ дан 29 November 2019 в 21:35
поделиться

Я никогда не делал то, что Вы пытаетесь сделать только MethodInfo. GetBaseDefinition () метод, кажется, то, что Вы ищете.

Это возвращает MethodInfo, этот метод является переопределяющим.

Из MSDN:

Если данный метод указан с новым ключевым словом (как в newslot, как описано в участниках Типа), данный метод возвращается.

0
ответ дан 29 November 2019 в 21:35
поделиться

Не похож на отражение, даст это Вам по умолчанию, таким образом, Вы будете иметь к самокрутке:

public static bool IsHidingMember( this PropertyInfo self )
{
    Type baseType = self.DeclaringType.BaseType;
    PropertyInfo baseProperty = baseType.GetProperty( self.Name, self.PropertyType );

    if ( baseProperty == null )
    {
        return false;
    }

    if ( baseProperty.DeclaringType == self.DeclaringType )
    {
        return false;
    }

    var baseMethodDefinition = baseProperty.GetGetMethod().GetBaseDefinition();
    var thisMethodDefinition = self.GetGetMethod().GetBaseDefinition();

    return baseMethodDefinition.DeclaringType != thisMethodDefinition.DeclaringType;
}

Не уверенный, как это будет работать с индексируемыми свойствами, однако!

5
ответ дан 29 November 2019 в 21:35
поделиться

Исправление при использовании VB свойство, которое Вы ищете, является "IsHideBySig". Это будет ложью в случае, что "новое" ключевое слово использовалось для определения метода/свойства.

В случае C# оба экземпляра производятся как "hidebysig". Спасибо за указание на это Greg. Я не понял, что только протестировал это в VB. Вот демонстрационный код VB, который будет репродукция это поведение.

Module Module1

    Class Foo
        Public Function SomeFunc() As Integer
            Return 42
        End Function
    End Class

    Class Bar
        Inherits Foo
        Public Shadows Function SomeFunc() As Integer
            Return 36
        End Function
    End Class

    Sub Main()
        Dim type = GetType(Bar)
        Dim func = type.GetMethod("SomeFunc")
        Stop
    End Sub

End Module
-1
ответ дан 29 November 2019 в 21:35
поделиться
Другие вопросы по тегам:

Похожие вопросы: