Setting all bool members of an object using reflection - c#

I have a struct that has a ton of named bool members. (Please leave good practices and such out of consideration now for the sake of the example).
I want to randomly set these values to either true or false, just for testing purposes.
How can I do this through reflection?
This is what I have so far:
Random r = new Random();
foreach (var bool_field in state.GetType().GetFields().Where(x => x.GetType() == false.GetType()))
{
bool_field.SetValue(state, r.Next() % 2 == 0 ? true : false);
}
Unfortunately, it never enters the loop.
UPDATE 1:
Here is how the SystemState struct looks like, which is the type of the state variable. It is filled with bool auto properties.
public struct SystemState
{
...
public bool CanYouHelpMeOnThisOne { get; set; }
...
}
UPDATE 2:
The solution posted below seems nice, but it does not work. The reason is that SystemState is a struct not a class. Therefor it is a Value type not a Reference type, so calling the SetValue method has no effect. After changing SystemState to class, the below solution works perfectly.
Now is there any other way, to achieve this without changing SystemState to class?

At first you need to change the Where clause:
x => x.FieldType == false.GetType()
As the type of x is FieldInfo
Since the last OP's edit it's not fields there, but properties. So, you should use GetProperties to get the list of properties, and compare the PropertyType, as x would be PropertyInfo then. Also the SetValue method is gonna to have the other signature.
foreach (var bool_field in state.GetType()
.GetProperties()
.Where(x => x.PropertyType == false.GetType()))
{
bool_field.SetValue(state, r.Next() % 2 == 0 ? true : false, null);
}
Based on OP's comments, if you do want to access the backing fields, you can use the following code:
var fs = state.GetType()
.GetFields(BindingFlags.Instance | BindingFlags.NonPublic)
.Where(x => x.FieldType == typeof(bool));
foreach (var f in fs)
{
f.SetValue(state, true);
}
The overload of GetFields without arguments returns all the public fields of the current Type. While in your case you need the private ones, so use the Type.GetFields Method (BindingFlags) with the suitable BindingFlags.

Related

Parse enum skipping Obsolete

How to skip obsolete values when I'm casting my int values to enums? I have minimum working example below:
using System;
public class Program
{
public static void Main()
{
int valueInt = 1;
var en = (TestObsolete)valueInt;
Console.WriteLine(en);
}
}
enum TestObsolete
{
Undefined,
[Obsolete]
ValueA = 1,
ValueB=1,
}
I'm getting ValueA, but expecting to get ValueB. Especially I'm interested in generic method with following signature:
public static T ParseEnumWithoutObsolete<T>(int val) where T: struct {
I tried to do something like that:
T #enum;
var enumValues = Enum.GetValues(typeof(T)).Cast<T>();
var obsoleteValues = enumValues.Where(a => typeof(T).GetField(a.ToString()).CustomAttributes.Any(t => t is ObsoleteAttribute));
var activeValues = enumValues.Except(obsoleteValues);
but stuck in the next step.
I'm getting ValueA, but expecting to get ValueB.
You're getting the value represented by the integer 1. The fact that you're seeing that as ValueA has nothing to do with Parse, and everything to do with ToString.
It's really, really important to bear in mind that when you have a value of an enum type, it's really just an integer. There can be several names for the same integer value, and they're completely indistinguishable when you've just got the value.
It sounds to me like what you really want to do - possibly in addition to your parsing method - is write a ToStringWithoutObsolete method. That could map values to names, but only for values which don't have the obsolete attribute. Note that using typeof(T).GetField(a.ToString()) anywhere in your code will make the results unpredictable. It would be better to get all the static fields within the enum type. So for example:
var valueToName = typeof(T)
.GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static)
.Where(f => !f.IsDefined(typeof(ObsoleteAttribute), false))
.ToDictionary(f => (T) f.GetValue(null),
f => f.Name);

efficient way to check for changes in a "calculation" class

I have the following "calculation" class.
public class Foo
{
private int? _sum = 0;
public int Sum
{
get
{
if (_sum == null)
_sum = 1 + 1; //simple code to show "some" calculation happens...
return _sum.GetValueOrDefault();
}
}
}
In this example there is only 1 Field/Member but in my real class there are around 50 Members, that all look similar just with different value calculations.
In the class I also have a Recalc method.
This Recalc method does 4 things
Save the old values
set all fields to null
calls the getter of every member
Checks if the old values differ from the newvalues and does related stuff
I am not sure whats the best way to store the old values and check for changes with the new values.
My current implementation is this:
public string GetValuesKey()
{
//again this method only handles the 1 Member and not all 50 in real app its string.Format("{0}|{1}|{2}|...{49}|{50}|", ....);
return string.Format("{0}|", this.Sum);
}
public void Recalc()
{
var oldValues = GetValuesKey();
//set all fields to null
//call the getters
var newValues = GetValuesKey();
if (oldValues != newValues)
{
//something changed...
}
}
But with this code there is a memory/performance issue since I am doing boxing with the struct (decimal) writing to a reference type (string).
I kind of want to prevent doing 50 additional fields (something like _oldSum) for all the members.
I just need to check if any member has changed during the Recalc procedure.
Just in Case, I cannot do the following code.
public void Recalc()
{
var changes = false;
var oldValue = this.Sum;
_sum = null;
var newValue = this.Sum;
if (oldValue != newValue)
changes = true;
//check next member
oldValue = this.Sum2;
_sum2 = null;
newValue = this.Sum2;
if (oldValue != newValue)
changes = true;
//check next member and so on...
}
Since I need to set all fields to null first and only AFTER all of them have been set to null I can execute the getters, since the members are dependant on each other for exmple if the Sum Member would aggregate two other members and they havent been set to null first they would still have old values.
So I need a way to store something that represents all values before setting the fields null and after calling the getter of the members a way to check for changes.
Any help is welcome.
Edit:
Here is the code, I wrote to test performance/memory:
http://pastebin.com/3WiNJHyS
Instead of combining all values in a string and have some pefomance hit on that string construction - put all values in array (of decimal), then set all fields to null, make your calculation and compare arrays of old and new values.
If you don't want to write yourself all the 50 _oldValue fields, the only alternative is to use Reflection, that implies some boxing/unboxing, so performance will not be the best possible.
Anyway, in the following implementation I assume that in the Foo class the members that are involved in the calculation are all and the only ones that are properties of type decimal?.
Otherwise, we need a more complicated solution, with BindingFlags, and/or Attribute on every field/property involved, and so on.
public void Recalc()
{
var propertyInfos = GetType()
.GetProperties()
.Where(pInfo => pInfo.PropertyType.IsValueType);
var fieldInfos = GetType()
.GetFields()
.Where(fInfo => fInfo.FieldType.IsValueType);
//create a dictionary with all the old values
//obtained from the backing fields.
var oldValueDictionary = fieldInfos.ToDictionary(
fInfo => fInfo.Name,
fInfo => (decimal?)fInfo.GetValue(this));
//set all properties to null
foreach (var pInfo in propertyInfos)
pInfo.SetValue(this, null);
//call all the getters to calculate the new values
foreach (var pInfo in propertyInfos)
pInfo.GetValue(this);
//compare new field values with the old ones stored in the dictionary;
//if only one different is found, the if is entered.
if (fieldInfos.Any(fInfo =>
(decimal?)fInfo.GetValue(this) != oldValueDictionary[fInfo.Name]))
{
//do stuffs
}
}
As a final note, your class configuration is very strange. Are you sure that setting all the calculations in the getters is the best choice? Maybe you should re-think about you design. One task is to retrieve a property value (a getter), another task is to calculate something (starting from some value stored in the backing fields)...

Compare 2 object of the same class

Recently, I ran into a problem of comparing 2 objects of the same class in C#. I need to know which fields/properties are changed.
Here is the example:
SampleClass
{
string sampleField1;
int sampleField2;
CustomClass sampleField3;
}
And I have 2 SampleClass object, object1 and object2, for example.
These 2 objects have some different field value.
Can anyone know the best approach to get which fields are different?
And how to get the (string) names of that different fields/properties?
I heard of Reflection in .Net. Is that the best approach in this situation?
And if we didn't have the CustomClass field? (I just make this field for a more general approach, that field does not exist in my case)
If you want Generic way to get all changed properties
you can use this method (and it is using reflection ^_^ )
public List<string> GetChangedProperties(object obj1, object obj2)
{
List<string> result = new List<string>();
if(obj1 == null || obj2 == null )
// just return empty result
return result;
if (obj1.GetType() != obj2.GetType())
throw new InvalidOperationException("Two objects should be from the same type");
Type objectType = obj1.GetType();
// check if the objects are primitive types
if (objectType.IsPrimitive || objectType == typeof(Decimal) || objectType == typeof(String) )
{
// here we shouldn't get properties because its just primitive :)
if (!object.Equals(obj1, obj2))
result.Add("Value");
return result;
}
var properties = objectType.GetProperties();
foreach (var property in properties)
{
if (!object.Equals(property.GetValue(obj1), property.GetValue(obj2)))
{
result.Add(property.Name);
}
}
return result;
}
Please note that this method only gets Primitive type properties that have changed and reference type properties that refer to the same instance
EDIT: Added validation in case if obj1 or obj2 is primitive type (int,string ... ) because I tried to pass string object and it will give an error
also fixed bug of checking whether the two values are equal
A slight modification of another answer posted here, but this one works with properties that are not string types, doesn't use an internal list and does automatic some preliminary type checking as it's generic:
public IEnumerable<string> ChangedFields<T>(T first, T second)
{
if (obj1.GetType() != obj2.GetType())
throw new ArgumentOutOfRangeException("Objects should be of the same type");
var properties = first
.GetType()
.GetProperties();
foreach (var property in properties)
{
if(!object.Equals(property.GetValue(first), property.GetValue(second)))
{
yield return property.Name;
}
}
}
If you need to compare two objects as part of your business logic reflection is the way to go, unless of course you can write comparator classes for each type.
If you want to compare two objects at run time during debugging, there is a neat plugin called Oz Code that can do that for you, something like this:

Comparing the value of a property in two instances

I think I'm having boxing issues
foreach(var p in item.GetType().GetProperties().
Where(p => p.GetValue(original, null) is ValueType))
{
var originalValue = p.GetValue(original, null);
var modifiedValue = p.GetValue(item, null);
if (!originalValue.Equals(modifiedValue))
kvpData.AppendFormat("{0}={1}&", p.Name, originalValue);
}
originalValue is never equal to modifiedValue, Im guessing it's because they are boxed inside Object. But how do I fix it?
It is not a boxing issue. Equals is a virtual method, which the boxed value types override just fine.
However, I am not sure what the issue is. Could it be that there aren’t actually any matching properties? Remember that GetProperties() without any parameters will only return public properties. If the properties you need are private, you need to add some BindingFlags:
GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
(I’m assuming here that you don’t want static properties.)
Are you also sure that it is actually properties that you are after and not fields? Remember that if you declare something as
public string Name;
then it’s a field, whereas
public string Name { get; set; }
is a property. If it’s actually fields you need, you need to use GetFields() instead of GetProperties() with the same binding flags.
Linq is a great tool, but I'm not sure why you're using it here. You're actually causing the set of properties to get iterated twice, which is very expensive. I'd write the code without Linq. Also, there's no need to get the value more than once, which is again very expensive. Give this code a try. It avoids the flaws I pointed out and was comparing correctly when I made and tested a dummy class with it:
foreach(PropertyInfo p in item.GetType().GetProperties())
{
if (p.PropertyType.BaseType == typeof(ValueType) || p.PropertyType == typeof(string))
{
var originalValue = p.GetValue(original, null);
var modifiedValue = p.GetValue(item, null);
if (originalValue != modifiedValue) kvpData.AppendFormat("{0}={1}&", p.Name, originalValue);
}
}
Also, note that strings are not a ValueType although they do implement a value comparison.
From MSDN: Object.Equals :
The default implementation of Equals supports reference equality for
reference types, and bitwise equality for value types. Reference
equality means the object references that are compared refer to the
same object. Bitwise equality means the objects that are compared have
the same binary representation.
That means that in your case this 2 objects (if they are reference types) are never point to the same instance.
There is no an easy way to resolve this in so generic way as you would like to do.
But you can implement (just an example) an IComparable on those types you gonna to compare, and after in this iteration check if the type of the value rturned implements that interface, so cast and call it's implemented IComparable.CompareTo method.
You can check if the object implements specified interfacce, in this current case IComparable, you can do something like this:
originalValue .GetType().GetInterfaces().Any(x =>
x.IsGenericType && x.GetGenericTypeDefinition() == typeof(IComparable))
Hope this helps.

Extract a generic value using reflection

I have the following interface in my project.
public interface Setting<T>
{
T Value { get; set; }
}
Using reflection, I would like to examine properties that implement this interface and extract Value.
So far I have written this, which successfully creates a list of properties that implement Setting.
var properties = from p in obj.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public)
where p.PropertyType.GetInterfaces().Any(x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof(IAplSetting<>))
select p;
Next I would like to do this: (Please ignore the undefined variables, you can assume that they really do exist in my actual code.)
foreach (var property in properties)
{
dictionary.Add(property.Name, property.GetValue(_theObject, null).Value);
}
The problem is that GetValue returns an object. In order to access Value, I need to be able to cast to Setting<T>. How would I get Value and store it, without needing to know the exact type of T?
You could continue this approach with one more level of indirection:
object settingsObject = property.GetValue(_theObject, null);
dictionary.Add(
property.Name,
settingsObject.GetType().GetProperty("Value")
.GetValue(settingsObject, null));
If you're using dynamic (re: your comment about ExpandoObject), this can be much simpler:
dynamic settingsObject = property.GetValue(_theObject, null);
dictionary.Add(property.Name, settingsObject.Value);

Categories