Let's assume I have a class ClassWithMember
class ClassWithMember
{
int myIntMember = 10;
}
How do I get the default value 10 of the myIntMember member by System.Type?
I'm currently struggling around with reflections by all I retreive is the default value of int (0) not the classes default member (10)..
You can try something like this:
var field = typeof(ClassWithMember).GetField("myIntMember",
BindingFlags.Instance | BindingFlags.NonPublic);
var value = (int)field.GetValue(new ClassWithMember());
The trick here is to instantiate an instance.
Try creating an instance an retreive the value with reflection.
If you're in control of the code for ClassWithMember, you could take a completely different approach to this by using the [DefaultValue] attribute from System.ComponentModel. Basically, what you'd do is write something like this:
class ClassWithMember
{
public ClassWithMember()
{
SetDefaultValues();
}
[DefaultValue(5)]
public MyIntMember { get; set; }
}
And then have a function like this somewhere, perhaps in a base class:
public void SetDefaultValues()
{
foreach (PropertyDescriptor prop in TypeDescriptor.GetProperties(this))
{
DefaultValueAttribute a = prop.Attributes[typeof(DefaultValueAttribute)] as DefaultValueAttribute;
if (a == null)
continue;
prop.SetValue(this, a.Value);
}
}
So now, you have a situation where you can easily retrieve the default values using Reflection.
Keep in mind that this is going to be quite a lot slower due to the Reflection requirement, so if this code gets instantiated a lot, you'll probably want to find a different approach. Also, it won't work with non-value types, due to a limitation with the .NET Framework's attribute support.
You can still use Activator.CreateInstance to create a MonoBehaviour/ScriptableObject and check its values, if it's simply for the sake of checking the default Values. Make sure to use DestroyImmediate afterwards ;-)
Related
There's all kinds of really awesome info on how to iterate through all of the properties of a class. What I want to do, however, is iterate through them and instantiate each property as new in the constructor... The class is an aggregate class representing a collection of entity framework model objects/classes. I could instantiate each in turn but that is going to be huge and a problem for maintenance when I decide to add another table to the database...
public class ClsAggModel {
public ClsAggModel() {
foreach (PropertyInfo props in this.GetType().GetProperties()) {
props.SetValue = new props.GetType(); //problem here!
}
}
public clsItem1 pProp1{ get; set; }
public clsItem2 pProp2{ get; set; }
//...and so on
The problem is that the compiler doesn't seem to know what props is at this point:
The type or namespace name 'props' could not be found (are you missing
a using directive or an assembly reference?)
which seems kind of strange since I just i stantiated it in the loop signature. I could fill out each property and do the private variable and all that jazz but what good is reflection if you can't abuse it?
Any tips?
You can not create instance on base of .GetType() in this manner.
This will not work:
new props.GetType();
You should try using:
Activator.CreateInstance(props.GetType());
Based on already provided solutions your code should look like this:
public class ClsAggModel {
public ClsAggModel() {
foreach (PropertyInfo prop in this.GetType().GetProperties()) {
var newValue = Activator.CreateInstance(prop.GetType());
prop.SetValue(this, newValue);
}
}
public clsItem1 pProp1{ get; set; }
public clsItem2 pProp2{ get; set; }
Keep in mind that all properties types must allow dynamic creation, by providing a default constructor (it is automatically there, if other constructor is not defined).
Assuming you want to call a default created type use the activator like this
props.SetValue(this, Activator.CreateInstance(props.GetType()));
Note, this will still fail if there is no default constructor. Because you are using reflection your compiler can no longer check for this.
Note 2: Be vary carefully with abusing reflection. it's a sure way to shoot yourself in the foot sooner or later.
Update of course setvalue is a method, changed this
I have a data class with several members
public interface IEquipmentHolder
{
ITypedServiceProvider<IGrabberChannel> VideoChannels { get; }
ITypedServiceProvider<IMicrophone> Microphones { get; }
ITypedServiceProvider<ISpeaker> Speakers { get; }
...
}
and a function
void visitChilds<T>(ITypedServiceProvider<T> childsList) where T : INamedComponent
{
...
}
In some place of my code, I want call the function for each field of the data class. So i do:
visitChilds(equipment.VideoChannels);
visitChilds(equipment.Microphones);
...
But, probably I am going to add some new fields in the data class and don't want to forget to fix these place after that.
My question: is it possible to to call generic function for each data member of the class using reflection? if it is not, can we put compile time check for new fields in the c# code?
How often are you going to add more fields and 'forget' to update calling code?
How fast are you going to find out that you've forgotten to add a call to visitChilds()?
How about IEquipmentHolder has only one property ITypedServiceProvider<INamedComponent> Items { get; }?
Reflection is slower than direct calls (maybe you should emit IL?) and the additional code may be just not worth the 'improvement', especially if it will be easy to spot that new set it not visited.
Also consider, that adding a new set of INamedComponents requires a breaking change to IEquipmentHolder interface and all implementations.
You could use the Expression framework to generate a lambda that will call visitChilds for each property on the interface.
You'd need to use reflection to generate the expression, but this would be a one off hit. After that you'd have a dynamically compiled lambda you could call that would be a lot quicker.
I've done something similiar before whereby I convert an instance of an object into a Dictionary<string,object> where each key is the name of a property and the value is the value of the property. We generated a lambda for each type we wanted to convert, and it worked really well.
If ITypedServiceProvider is covariant, i.e., declared like this,
ITypedServiceProvider<out T>
{
...
}
then you could have
IEquipmentHolder
{
IEnumerable<ITypedServiceProvider<INamedComponent>>
NamedComponents { get; }
}
then your could do
void VisitChildren(IEquipmentHolder equipment)
{
foreach(var provider in equipment.NamedComponents)
{
provider.SomeMemberOfITypedServiceProvider();
}
}
following are my codes:
class Foo
{
public string Bar { get; private set; }
}
and
var prop = typeof(Foo).GetProperty("Bar");
if (prop != null)
{
// The property exists
var setter = prop.GetSetMethod(true);
if (setter != null)
{
// There's a setter
Console.WriteLine(setter.IsPublic);
}
}
yes, as you can imagine, this works perfectly right. but when there comes a inheritance, things are different:
class Foo
{
public string Bar { get; private set; }
}
class A : Foo
{
}
of course i changed this line:
var prop = typeof(Foo).GetProperty("Bar");
to
var prop = typeof(A).GetProperty("Bar");
then, the setter gets to null, and console print nothing!
so...why?
btw, is there some workaround to make this happen or totally another way to?
any help would be appreciated. thanks.
The general solution is to call
var prop = GetType().GetProperty("Bar").DeclaringType.GetProperty("Bar");
Which is not very intuitive, i agree.
so...why?
As far as A is concerned, Bar is read-only - you can't call the setter from A, so it does make sense that there's no setter when you ask for the property with respect to A.
One alternative is to use binding flags to only ask for declared properties - and walk your way up the inheritance chain until you find the actual property declaration. It's a little bit odd that you have to do this, but it does make a certain amount of sense, as the property really is different depending on whether you're coming to it from the context of the declaring class or not.
I'm surprised by this behaviour - but not shocked.
You can set the private property with reflection by just using the SetValue method in the property info, even if you can't get the set method.
public class test
{
public test()
{
ting=10;
}
private int ting{get;set;}
public int tring
{
get
{
return ting;
}
}
}
void Main()
{
var t= new test();
//Below line giving error
Console.Write(t.GetType().GetProperty("tring").SetValue(t,20));
}
How to resolve this using reflection?
Well yes - the property can't be set. It's read-only, presumably deliberately.
If the designer of the class hasn't given you the opportunity of setting the value, you shouldn't be trying to set it. In many cases it would be impossible to do so, as the value may not even be backed by a field (think DateTime.Now) or may be computed some non-reversible way (as per Marcin's answer).
In this particular case if you were really devious you could get hold of the IL implementing tring.get, work out that it's fetching from the ting property, and then call that setter by reflection - but at that point you're going down a very dark path which you're almost certain to regret.
You can't do that, unless you know what is the backing field name. When you do, you can just set the field value, and it will reflect to property value.
Consider the situation when it would be possible and your property wouldn't be backed by a field (like that):
public string tring
{
get
{
return string.format("foo {0} foo", ting);
}
}
What should be desired output of setting that property?
My question stems from MVC's SelectList (and previous generations). Basically the class takes in an IEnumerable and uses the members you define as strings.
How does it interface with the object (casting, reflection?)
(probably redundant) How does it lookup the members as a string.
This is one facet of C# that I have been interested in but could never find examples of :(
EDIT:
I ended up using DataBinder.Eval() from System.Web.UI
It still has the overhead of reflection but makes things easier by allowing you to pass the object and a string containing the hierarchy of the member you want. Right now that doesn't really mean much, but this project was designed to take in Linq data, so not having to worry about it down the road makes my life a tad easier.
Thanks everyone for the help.
While I don't know about its implementation for sure, I'd expect it to use reflection.
Basically you call Type.GetProperty or Type.GetMethod to get the relevant member, then ask it for the value of that property for a specific instance (or call the method, etc). Alternatively there's Type.GetMembers, Type.GetMember etc.
If you want to be able to use "Person.Mother.Name" or similar "paths" you have to do that parsing yourself though, as far as I'm aware. (There may be bits of the framework to do it for you, but they're not in the reflection API.)
Here's a short but complete example:
using System;
using System.Reflection;
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
class Test
{
static void Main()
{
Person jon = new Person { Name = "Jon", Age = 33 };
ShowProperty(jon, "Name");
ShowProperty(jon, "Age");
}
static void ShowProperty(object target, string propertyName)
{
// We don't need no stinkin' error handling or validity
// checking (but you do if you want production code)
PropertyInfo property = target.GetType().GetProperty(propertyName);
object value = property.GetValue(target, null);
Console.WriteLine(value);
}
}
Yes, via reflection. Take a look at the Type class and associated methods. A good place to start might be here.
You can always look at MVC's source for examples too.