从 getter/setter 的 MethodInfo 中查找托管 PropertyInfo

发布于 2024-07-12 13:42:31 字数 123 浏览 6 评论 0原文

我使用反射在运行时进行一些类型分析。 如果我有一个 MethodInfo 实例, 我如何判断这是一个“真正的”方法还是属性的 getter/setter 方法? 如果它是一个属性,我如何找到它的托管 PropertyInfo?

I do some type analysis in runtime using Reflection. If I have a MethodInfo instance,
how can I figure out if this is a "real" method or is a getter/setter method of a property? And if it is a property, how can I find the its hosting PropertyInfo back?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

﹂绝世的画 2024-07-19 13:42:31

好吧,getter 和 setter 背后的方法是“真正的”方法。

重新跟踪回属性 - 模式(return 与 take 1 arg)将有助于缩小范围 - 但您必须对每个属性调用 GetGetMethod/GetSetMethod 才能找到该属性。

您可以可能尝试名称(少get__/set__) - 但这感觉很脆弱。 这是更长的版本(不使用 Name):

static PropertyInfo GetProperty(MethodInfo method)
{
    bool takesArg = method.GetParameters().Length == 1;
    bool hasReturn = method.ReturnType != typeof(void);
    if (takesArg == hasReturn) return null;
    if (takesArg)
    {
        return method.DeclaringType.GetProperties()
            .Where(prop => prop.GetSetMethod() == method).FirstOrDefault();
    }
    else
    {
        return method.DeclaringType.GetProperties()
            .Where(prop => prop.GetGetMethod() == method).FirstOrDefault();
    }
}

Well, the method behind a getter and setter are "real" methods.

Re tracking back to a property - the pattern (return vs take 1 arg) will help narrow it - but you'll have to call GetGetMethod/GetSetMethod on each to find the property.

You could probably try the Name (less get__/set__) - but that feels brittle. Here's the longer version (no use of Name):

static PropertyInfo GetProperty(MethodInfo method)
{
    bool takesArg = method.GetParameters().Length == 1;
    bool hasReturn = method.ReturnType != typeof(void);
    if (takesArg == hasReturn) return null;
    if (takesArg)
    {
        return method.DeclaringType.GetProperties()
            .Where(prop => prop.GetSetMethod() == method).FirstOrDefault();
    }
    else
    {
        return method.DeclaringType.GetProperties()
            .Where(prop => prop.GetGetMethod() == method).FirstOrDefault();
    }
}
别想她 2024-07-19 13:42:31

Ecma 335 指定(但不要求)编译器使用 get_/set_ 前缀(第 22.28 章)。 我不知道有什么语言可以违背这一建议。 让它变得简单:

public static PropertyInfo GetPropFromMethod(Type t, MethodInfo method) {
  if (!method.IsSpecialName) return null;
  return t.GetProperty(method.Name.Substring(4), 
    BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic);
}

Ecma 335 specifies (but does not demand) that compilers use the get_/set_ prefixes (chapter 22.28). I don't know any language that breaks that recommendation. Making it easy:

public static PropertyInfo GetPropFromMethod(Type t, MethodInfo method) {
  if (!method.IsSpecialName) return null;
  return t.GetProperty(method.Name.Substring(4), 
    BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic);
}
做个少女永远怀春 2024-07-19 13:42:31

Look into MethodBase.IsSpecialName. Methods which shouldn't be plainly visible, such as property accessors, event subscription methods and operator overloads use this flag.

To my knowledge, there isn't a way to find the PropertyInfo without iterating through the properties and comparing the methods.

寻梦旅人 2024-07-19 13:42:31

我真的很想将此作为评论,但我不能,因为我的代表不够高:(

Marc Gravell 的代码中有一个错误:如果它是一个索引器,它将返回 null,即使父属性存在。它很好有这种快速失败的情况,但我认为我们只能在它既没有返回值也没有参数的情况下这样做:

    [Pure]
    public static PropertyInfo GetParentProperty(this MethodInfo method)
    {
        if (method == null) throw new ArgumentNullException("method");
        var takesArg = method.GetParameters().Length == 1;
        var hasReturn = method.ReturnType != typeof(void);
        if (!(takesArg || hasReturn)) return null;

        if (takesArg && !hasReturn)
        {
            return method.DeclaringType.GetProperties().FirstOrDefault(prop => prop.GetSetMethod() == method);
        }
        else
        {
            return method.DeclaringType.GetProperties().FirstOrDefault(prop => prop.GetGetMethod() == method);
        }
    }

I'd really like to leave this as a comment, but I cant since my rep isnt high enough :(

Theres a bug in Marc Gravell's code: if its an indexer it will return null, even when a parent property exists. Its nice to have that quick-fail, but I think we can only do so when it has neither a return value or a parameter:

    [Pure]
    public static PropertyInfo GetParentProperty(this MethodInfo method)
    {
        if (method == null) throw new ArgumentNullException("method");
        var takesArg = method.GetParameters().Length == 1;
        var hasReturn = method.ReturnType != typeof(void);
        if (!(takesArg || hasReturn)) return null;

        if (takesArg && !hasReturn)
        {
            return method.DeclaringType.GetProperties().FirstOrDefault(prop => prop.GetSetMethod() == method);
        }
        else
        {
            return method.DeclaringType.GetProperties().FirstOrDefault(prop => prop.GetGetMethod() == method);
        }
    }
养猫人 2024-07-19 13:42:31

对于当今的 .NET,我相信以下内容与 Marc 的答案相同,但更简洁,而且可能更高效。 我可能错过了什么。

public static PropertyInfo? GetPropertyInfo(this MethodInfo getSetMethodInfo) 
    => getSetMethodInfo.DeclaringType?.GetProperties()
    .FirstOrDefault(prop => prop.GetSetMethod() == getSetMethodInfo 
    || prop.GetGetMethod() == getSetMethodInfo);

For present day .NET, I believe the following is equivalent to Marc's answer but more concise and maybe a slight bit more efficient. I may have missed something.

public static PropertyInfo? GetPropertyInfo(this MethodInfo getSetMethodInfo) 
    => getSetMethodInfo.DeclaringType?.GetProperties()
    .FirstOrDefault(prop => prop.GetSetMethod() == getSetMethodInfo 
    || prop.GetGetMethod() == getSetMethodInfo);
孤君无依 2024-07-19 13:42:31

使用的技巧是 BindingFlags.DeclaredOnlyIsSpecialName

The trick to play with is BindingFlags.DeclaredOnly and IsSpecialName

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文