재산이 '새로운'키워드로 상속 된 멤버를 숨길 때 반사는 어떻게 알려주나요?

StackOverflow https://stackoverflow.com/questions/288357

문제

그래서 내가 가지고 있다면 :

public class ChildClass : BaseClass
{
    public new virtual string TempProperty { get; set; }
}

public class BaseClass
{
    public virtual string TempProperty { get; set; }
}

Childclass가 Tempproperty의 기본 구현을 숨기고 있음을 확인하기 위해 반사를 어떻게 사용할 수 있습니까?

C#과 vb.net 사이에 응답이없는 대답을 원합니다.

도움이 되었습니까?

해결책

재산 자체가 아닌 재산 자체가 아닌 재산 자체가 아닌 재산의 방법을 다루어야합니다. 완전한 솔루션은 부족이 없는지 확인해야하지만 Get 메소드를 사용하지 않으므로 Get 메소드를 사용하겠습니다.

여러 가지 경우에 방출 된 IL을 살펴보면 기본 속성의 'get'방법은 메타 데이터 토큰을 갖습니다 (이것은 C# 컴파일러에서 나온 것입니다. hidebysig 그들의 방법을 숨기는 의미론에 따라,이 경우 방법은 hy hy-name) : :

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
}

그러므로 우리가 'get'방법이 재정의가 아니라고 가정하면, 기본 클래스에 그림자가있는 속성이 있는지 알고 싶습니다. 문제는 메소드가 다른 메소드 테이블 슬롯에 있기 때문에 실제로 섀도우가있는 메소드와 직접적인 관계가 없다는 것입니다. 그래서 우리가 실제로 말하는 것은 "기본 유형은 그림자 기준을 충족하는 메소드가 있습니까"라는 것입니다. 메소드가 있는지 여부에 따라 다릅니다. 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에서 답이 예라면이 질문에 대한 답은 실제로 비 결정적이라는 것을 의미합니다).

글쎄, 나는 이것이 내가 생각했던 것보다 실제로 훨씬 더 어려운 문제라는 것을 설명하는 것 외에이 모든 것이 얼마나 도움이되는지 잘 모르겠습니다 (또는 내가 알고 싶은 경우 정말 명백한 것을 놓쳤습니다! ). 그러나 바라건대 당신이하려는 일을 달성하는 데 도움이되는 충분한 내용이 있기를 바랍니다.

다른 팁

반사처럼 보이지 않으면 기본적으로 이것을 제공하므로 자신의 것을 굴려야합니다.

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

그러나 이것이 인덱스 속성과 어떻게 작동하는지 잘 모르겠습니다!

나는 당신이하려는 일을 한 적이 없지만 methodinfo.getBasedEfinition () 메소드는 당신이 찾고있는 것 같습니다.

이 메소드가 재정의하는 방법을 반환합니다.

MSDN에서 :

주어진 메소드가 새로운 키워드로 지정된 경우 (유형 멤버에 설명 된대로 NewsLot에서와 같이) 주어진 메소드가 반환됩니다.

수정, VB를 사용하는 경우 원하는 속성은 "ishidebysig"입니다. "새로운"키워드가 메소드/속성을 정의하는 데 사용 된 경우 거짓입니다.

C# 케이스에서는 두 인스턴스 모두 "hidebysig"로 출력됩니다. 그렉을 지적 해 주셔서 감사합니다. 나는 이것을 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
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top