28

So in my case i am doing discovery of the structure of a class using reflection. I need to be able to find out if a property is an auto-implemented property by the PropertyInfo object. I assume that the reflection API does not expose such functionality because auto-properties are C# dependent, but is there any workaround to get this information?

jason
  • 236,483
  • 35
  • 423
  • 525
Zoki
  • 303
  • 3
  • 6

2 Answers2

26

You could check to see if the get or set method is marked with the CompilerGenerated attribute. You could then combine that with looking for a private field that is marked with the CompilerGenerated attribute containing the name of the property and the string "BackingField".

Perhaps:

public static bool MightBeCouldBeMaybeAutoGeneratedInstanceProperty(
    this PropertyInfo info
) {
    bool mightBe = info.GetGetMethod()
                       .GetCustomAttributes(
                           typeof(CompilerGeneratedAttribute),
                           true
                       )
                       .Any();
    if (!mightBe) {
        return false;
    }


    bool maybe = info.DeclaringType
                     .GetFields(BindingFlags.NonPublic | BindingFlags.Instance)
                     .Where(f => f.Name.Contains(info.Name))
                     .Where(f => f.Name.Contains("BackingField"))
                     .Where(
                         f => f.GetCustomAttributes(
                             typeof(CompilerGeneratedAttribute),
                             true
                         ).Any()
                     )
                     .Any();

        return maybe;
    }

It's not fool proof, quite brittle and probably not portable to, say, Mono.

jason
  • 236,483
  • 35
  • 423
  • 525
  • Thanks a lot Jason, the Reflector told me the same in the meantime:) Should have thought of it earlier. – Zoki Feb 05 '10 at 21:02
  • 1
    @3o4eTo: Just be forewarned that this not fool proof, brittle and possibly not portable to Mono. – jason Feb 05 '10 at 21:07
  • Also take care of the exception when there is no getter on the property. – nawfal May 12 '13 at 11:22
  • True. Why do we need to check for the attribute? – vexe Dec 26 '13 at 11:54
  • In addition to the other restrictions, this will only work for auto-props generated by C#. VB.NET compiler uses the pattern of just putting prefixing `_` to the auto-prop name, but does include the `CompilerGeneratedAttribute` attribute. The F# compiler does not use apply that attribute and uses yet another naming convention. – Nick Strupat Jan 24 '16 at 23:44
  • @NickStrupat could you please give some hints if these compiler inconsistencies are still the same now in 2017? I can't find any detailed documentation about these. – Zoltán Tamási Jan 28 '17 at 10:33
15

This should do:

public static bool IsAutoProperty(this PropertyInfo prop)
{
    return prop.DeclaringType.GetFields(BindingFlags.NonPublic | BindingFlags.Instance)
                             .Any(f => f.Name.Contains("<" + prop.Name + ">"));
}

The reason is that for auto-properties the Name property of the backing FieldInfo would look like:

<PropertName>k__BackingField

Since characters < and > wouldn't appear for normal fields, a field with that kind of naming points to a backing field of an auto-property. As Jason says, its brittle still.

Or to make it a tad faster,

public static bool IsAutoProperty(this PropertyInfo prop)
{
    if (!prop.CanWrite || !prop.CanRead)
        return false;

    return prop.DeclaringType.GetFields(BindingFlags.NonPublic | BindingFlags.Instance)
                             .Any(f => f.Name.Contains("<" + prop.Name + ">"));
}
nawfal
  • 70,104
  • 56
  • 326
  • 368