tags:

views:

66

answers:

3

Hi guys.

I'm doing some dynamic code generation using Reflection, and I've come across a situation where I need to get the backing field of a property (if it has one) in order to use its FieldInfo object.

Now, I know you can use

.IsDefined(typeof(CompilerGeneratedAttribute), false);

on a FieldInfo to discover whether it's autogenerated, so I assume there's a similar thing for Properties which auto-generate fields?

Cheers, Ed

+3  A: 

There is no built-in method for doing this since the presence of a property does not necessarily guarantee the presence of a backing field.

I found this article which explains one way of doing it. It involves getting the IL of the property's setter and parsing it looking for evidence of a field being set.

Andrew Hare
Yeah, I understand that Properties are just an abstraction of accessor methods, but I'd assumed the Compiler would put a flag on auto-generated get; methods, in the same way as the fields. It would seem that that is not the case!
Ed Woodcock
@Ed: The compiler does indeed apply the `CompilerGeneratedAttribute` to the `get_` and `set_` methods.
Adam Robinson
@Adam sorry, yes, totally skipped the first bit of your answer when I read it.
Ed Woodcock
+1  A: 

The get_ and set_ methods for properties also get the CompilerGeneratedAttributed applied to them. While there is no strong coupling through attributes, there is a naming convention used for the backing fields of an auto property:

public string Foo { get; set;}

Produces a private string <Foo>k__BackingField member (the < and > here are part of the name, as they're legal in IL but not in C#; they have nothing to do with generics).

As an example, this will get a list of all of the auto properties in a class, along with their backing fields:

t.GetProperties().Where(p => 
    (p.GetGetMethod() ?? p.GetSetMethod()).IsDefined(typeof(CompilerGeneratedAttribute), false))
   .Select(p => new 
   { 
      Property = p, 
      Field = t.GetField(string.Format("<{0}>k__BackingField", p.Name),
          System.Reflection.BindingFlags.NonPublic | 
          System.Reflection.BindingFlags.Instance) 
   });
Adam Robinson
I'm not sure that is quite reliable enough, are there other instances where this flag would be added to the method?
Ed Woodcock
@Ed: There are no instances where it would be added to a method associated with a property. Unless something changes in future versions of the C# compiler, this approach is 100% reliable.
Adam Robinson
I used this in the end, and it seems to work great, thanks!
Ed Woodcock
A: 

Andrew is right.

Actually, a property is just a "pointer" to methods, usually getters/setters when they are generated by Visual Studio or other high level language (most of the time).

Parsing the setter is not easy, though. And, since internally setters are just another vanilla methods, they can use more than one fields, or none at all, or even call another methods. Perhaps you can come up with a solution for the common scenarios, but you have to parse the IL bytecode.

Daniel Dolz
It seems pretty clear from his question that he's referring to auto properties, which can be reliably linked to a backing field.
Adam Robinson