Reflection: Get FieldInfo from PropertyInfo - c#

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

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

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 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.

Related

In C#, How to Change the DefaultValue Attribute of a Property in a Class that is Not Inheritable?

Here is my situation:
I have a 3rd party Component Control which I successfully inherited,
and now I am doing some custumization to it.
Part of that customization, is to change the DefaultValues of some properties it has.
So far it all went OK,
but this control has some "Sub" Classes in it, that I want to change their propeties' DefaultValues too.
By "Sub" Classes I mean:
Let's say my control is called SomeControl,
so it has properties in it, but it also has a property that is expandable,
like: SomeControl.Rows,
The .Rows property returns a RowCollection which has its own properties.
So this is what I mean by "Sub" Class (please correct me if there's a better term for this)
In any case, If I want to change some DefaultValues in the RowCollection class,
I need to inherit it too.
The propblem is that RowCollection's Ctor is internal, so I cannot inherit that class.
So is there any other way for me to change the DefaultValue attribute for a property in a class that I cannot inherit?
Maybe via reflection?
I nee to change it for an instance(object) that I have existing - one instance,
and not for the class in general.. (since after 1 object is created from it, no more are created..)
Thank you
Summary: I don't think it is possible to do this via reflection, but here is how I would do it:
First get the property you want:
var defValAttr = typeof (SomeControl.RowCollection)
.GetProperty("yourProperty")
.GetCustomAttributes(typeof(DefaultValueAttribute), false)
.First()
as DefaultValueAttribute;
DefaultValueAttribute has a .Value property, which is readonly. To modify it you need reflection again to change the private .value field:
var valueField= typeof (DefaultValueAttribute)
.GetField("value", BindingFlags.NonPublic
| BindingFlags.GetField
| BindingFlags.Instance);
valueField.SetValue(defValAttr, yourNewDefaultValue);
I have not tested this myself, but as far as I know this will not work. The objects returned by GetCustomAttributes are not the actual attributes; you can get the values of the real attributes this way, but you cannot change them. (see Can attributes be added dynamically in C#?)
However, even if this would work, it would change the DefaultValue for all instances of SomeControl.Rows, whether they are within your custom derived control or in the base control. There is no way to change only the DefaultValue of a single instance, since the this value is stored only once per class, not once per instance. It would be very wasteful if there was a copy of each attribute for each instance of an object.
So in conclusion, I don't think there is a way to do this.
As an alternative, you could decompile the third-party assembly and add your own assembly with InternalsVisibleTo, that way you can access the internal constructor.
Addendum: There may still be a way to do this, depending on what sort of attribute you want to change. The attributes accessible via reflection are as I said probably unchangeable. However The visual studio editor and the whole WPF component model actually uses a TypeDescriptor to manage attributes on top of the basic attribute system built into the language. You may be able to change the attributes used by the TypeProvider, and if code later accesses the attributes via TypeDescriptor, it may see the changed values.
The following is again untested:
var instanceOfRow = instanceOfYourControl.Rows;
var defValAttr = TypeDescriptor
.GetProperties(instanceOfRow)["yourProperty"]
.Attributes[typeof (DefaultValueAttribute)]
as DefaultValueAttribute;
var valueField= typeof (DefaultValueAttribute)
.GetField("value", BindingFlags.NonPublic
| BindingFlags.GetField
| BindingFlags.Instance);
valueField.SetValue(defValAttr, yourNewDefaultValue);

Using Impromptu-Interface to obtain the type of a property

I've got a complex solution where part of the problem is model binding from a HTML form to a series of database backed and relatively complex Entity Framework DbSets.
The thing is, we have an EF defined domain model that encapsulates everything we'd need to know about the data we're capturing; but the admins of the project want to be able to make a questionnaire-like form, that allows them to choose any of the members of this domain.
Anyway, that's not the problem as such, as it largely works, at least it works very well for simple members, strings, dates, bools and so on. The tricky part was managing members that have multiple fields, such as an Address object.
A solution has been to use Reflection to set the value of the domain that we receive from the form post, but of course that has its overhead and I'm driven to find a nicer way of doing things; In my research I found out about the 'Impromptu interface' project which promises a lot of speed increase over Reflection, but I have one simple problem.
It's all well and good to Get and Set properties:
var val = Impromptu.InvokeGet(domain, "fieldName");
Impromptu.InvokeSet(domain, "fieldName", value);
But what I need to do is to find the Type of the property.
So far I can still only see how to do that with Reflection:
PropertyInfo pi = domain.GetType().GetProperty("Name", BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);
if (pi.GetValue(domain) is IMyInterface)
{
// ? profit
}
So: Is it possible to do this with Impromptu?
I need to cast the property to my Interface as it has members that convert html form posts into my EF objects.
The general question you ask, can I use ImpromptuInterface to query property types, the answer is no, the DLR doesn't have the function, reflection is it.
However, the example you give using reflection isn't testing the property type, it's testing the runtime type of the value so that would still work with Impromptu without reflection.
var val = Impromptu.InvokeGet(domain, "fieldName");
if(val is IMyInterface){
// ? profit
}
Also if you only want properties look at FastMember. It choose the fastest access mechanism based on the type of object.

How can I get a variable/field name through reflection on properties?

Lets say you have:
PropertyInfo propInfo; // Assume it was already initialized with property of a private field
(private int m_Number)
If I'll do propInfo.PropertyType.Name I guess I will get something like int32 or int.
Two questions:
1. How can I extract the variable name "m_Number" through propInfo.
Note: Once I was able to do so by iterating a FieldInfo instead of propInfo.
2. If I want to use reflection to know all kind of fields of a given class, what should be the right way:
A. Iterating over all properties(in assumption every field has a property)
B. Iterating over all the fields directely.
Thanks
A property is not necessarily related to a field - in fact, a property is a little more than a syntactic sugar on top of a pair of functions.
If your code uses some sort of a convention for naming variables that back properties (such as prepending them with m_, as in your example) you could rely upon that convention to retrieve the variable name. In all other cases, there is no direct connection, and no way to retrieve that relationship through the reflection API.

Workaround for Reflection Bug in Dotfuscator?

Greetings all,
I am calling Type.GetProperties(), but after running Dotfuscator, it is returning zero items, when it returned more than zero before.
public class Test
{
public int Number { get; set; }
public void ShowInfo()
{
Type type = this.GetType();
PropertyInfo[] props = type.GetProperties();
Console.WriteLine("type [" + type.Name + "] props count: " + props.Length);
}
}
If I exclude the "Number" property from renaming within Dotfuscator, then it works, but otherwise it doesn't. However, it is not possible for me to do this for all properties in my project, as it would lead to possible bugs.
Are there any workarounds for this method? Or even other "free" obfuscation applications I could use?
I have already tried looking on their website to submit a bug, but I am only using the community edition so there doesn't seem to be as much support for it.
Dotfuscator automatically strips properties (which are just metadata anyway - the real work is done by the get/set pair of methods that are automatically created) during renaming. It also renames the underlying get/set methods as well. Depending on what you are trying to do, you'll need to exclude either the property metadata itself, or the get/set methods (or possibly both) from renaming.
If you need to keep the property metadata intact (for example, to simply list the properties in a Type), you can instruct Dotfuscator to exclude properties from renaming by checking them in the tree view on the Renaming Exclusions tab or using a custom regex property rule. This will only exclude the property metadata - the get/set methods will still be renamed.
If you need to keep the get/set methods (because, for example, you are trying to get or set a property's value by reflection), you can instruct Dotfuscator to exclude those methods from renaming by expanding the property in the tree view and checking the get/set methods underneath, or by using a custom regex method rule.
As the process of obfuscation is not limited to renaming your class members, you can't be sure of that. That's the problem with obfuscation: You basically can't make any assumptions about your class anymore regarding the result of reflection. The only way I can think of is to not use reflection but expressions.
Have a look at this question and its answer to know, what I mean with "expressions": How to raise PropertyChanged event without using string name

Can attributes be added dynamically in C#?

Is it possible to add attributes at runtime or to change the value of an attribute at runtime?
This really depends on what exactly you're trying to accomplish.
The System.ComponentModel.TypeDescriptor stuff can be used to add attributes to types, properties and object instances, and it has the limitation that you have to use it to retrieve those properties as well. If you're writing the code that consumes those attributes, and you can live within those limitations, then I'd definitely suggest it.
As far as I know, the PropertyGrid control and the visual studio design surface are the only things in the BCL that consume the TypeDescriptor stuff. In fact, that's how they do about half the things they really need to do.
Attributes are static metadata. Assemblies, modules, types, members, parameters, and return values aren't first-class objects in C# (e.g., the System.Type class is merely a reflected representation of a type). You can get an instance of an attribute for a type and change the properties if they're writable but that won't affect the attribute as it is applied to the type.
You can't. One workaround might be to generate a derived class at runtime and adding the attribute, although this is probably bit of an overkill.
Well, just to be different, I found an article that references using Reflection.Emit to do so.
Here's the link: http://www.codeproject.com/KB/cs/dotnetattributes.aspx , you will also want to look into some of the comments at the bottom of the article, because possible approaches are discussed.
No, it's not.
Attributes are meta-data and stored in binary-form in the compiled assembly (that's also why you can only use simple types in them).
I don't believe so. Even if I'm wrong, the best you can hope for is adding them to an entire Type, never an instance of a Type.
If you need something to be able to added dynamically, c# attributes aren't the way. Look into storing the data in xml. I recently did a project that i started w/ attributes, but eventually moved to serialization w/ xml.
Why do you need to? Attributes give extra information for reflection, but if you externally know which properties you want you don't need them.
You could store meta data externally relatively easily in a database or resource file.
Like mentionned in a comment below by Deczaloth, I think that metadata is fixed at compile time. I achieve it by creating a dynamic object where I override GetType() or use GetCustomType() and writing my own type. Using this then you could...
I tried very hard with System.ComponentModel.TypeDescriptor without success. That does not means it can't work but I would like to see code for that.
In counter part, I wanted to change some Attribute values.
I did 2 functions which work fine for that purpose.
// ************************************************************************
public static void SetObjectPropertyDescription(this Type typeOfObject, string propertyName, string description)
{
PropertyDescriptor pd = TypeDescriptor.GetProperties(typeOfObject)[propertyName];
var att = pd.Attributes[typeof(DescriptionAttribute)] as DescriptionAttribute;
if (att != null)
{
var fieldDescription = att.GetType().GetField("description", BindingFlags.NonPublic | BindingFlags.Instance);
if (fieldDescription != null)
{
fieldDescription.SetValue(att, description);
}
}
}
// ************************************************************************
public static void SetPropertyAttributReadOnly(this Type typeOfObject, string propertyName, bool isReadOnly)
{
PropertyDescriptor pd = TypeDescriptor.GetProperties(typeOfObject)[propertyName];
var att = pd.Attributes[typeof(ReadOnlyAttribute)] as ReadOnlyAttribute;
if (att != null)
{
var fieldDescription = att.GetType().GetField("isReadOnly", BindingFlags.NonPublic | BindingFlags.Instance);
if (fieldDescription != null)
{
fieldDescription.SetValue(att, isReadOnly);
}
}
}
When faced with this situation, yet another solution might be questioning you code design and search for a more object-oriented way. For me, struggling with unpleasant reflection work arounds is the last resort. And my first reaction to this situation would be re-designing the code. Think of the following code, which tries to solve the problem that you have to add an attribute to a third-party class you are using.
class Employee {} // This one is third-party.
And you have code like
var specialEmployee = new Employee();
// Here you need an employee with a special behaviour and want to add an attribute to the employee but you cannot.
The solution might be extracting a class inheriting from the Employee class and decorating it with your attribute:
[SpecialAttribute]
class SpecialEmployee : Employee
{
}
When you create an instance of this new class
var specialEmployee = new SpecialEmployee();
you can distinguish this specialEmployee object from other employee objects. If appropriate, you may want to make this SpecialEmployee a private nested class.

Categories