Find difference between two objects in C# - c#

I'm looking for a way to find the difference between the values of properties between two objects of the same type.
I've been working from the example in this stack overflow question:
Finding property differences between two C# objects
This is what I have so far:
public static string Compaire<T>(T initial, T final)
{
Type currentType = initial.GetType();
PropertyInfo[] props = currentType.GetProperties();
StringBuilder sb = new StringBuilder();
foreach (var prop in props)
{
Type equatable = prop.PropertyType.GetInterface("System.IEquatable");
if (equatable != null)
{
var i = prop.GetValue(initial);
var f = prop.GetValue(final);
if (i!= null && f != null && !i.Equals(f))
{
sb.Append(String.Format(_"{0}.{1} has changed from {2} to {3}. ", currentType.BaseType.Name, prop.Name, i, f));
}
}
}
return sb.ToString();
}
This is working for most cases however, nullable properties (like Nullable int for example) are not getting compared because (I think) they are not being unboxed and nullable isn't implemented with IEquatable.
Using this method of reflection, is it possible to compare nullables while still avoiding entities that have been disposed (e.g. "The ObjectContext instance has been disposed and can no longer be used for operations that require a connection")?

Maybe this project can fit your needs:
CompareNetObjects

You could use object.Equals(i,f) and omit the check for IEquatable. If it is neccessary but you would like to include nullables you could include them the following way:
if (prop.PropertyType.IsGenericType)
{
if (prop.PropertyType.GetGenericTypeDefinition().Equals(typeof(Nullable<>)))
{
Type typeParameter = prop.PropertyType.GetGenericArguments()[0];
var i = prop.GetValue(initial);
var f = prop.GetValue(final);
if(object.Equals(i,f))
{
//...
}
}
}
So you check explicitly for Nullables.
The first line checks if the type is generic (true for Nullable List etc.) The second gets the underlying generic type (Nullable<>, List<>) and compares it with the Nullable<> type. The third line gets the first (and in case of Nullable<> only) parameter, just for the case you are interested in what type the Nullable is. So you will get int for Nullable. It is not needed in the code I written, but perhaps you are interested in it. Then the values of both properties are read and compared.

Related

How to use variable type in as operator

For example:I have 2 variable (value ) & (property) i want to check is cast possible for value? We do not know the type of variables, How to check if cast is possible?
var value = Reader[item];
PropertyInfo property = properties.Where(x => x.Name == item).FirstOrDefault();
var type=property.PropertyType;//Or property.ReflectedType
var cs= value as type // Error: type is variable but is used like a Type
if (cs!=null){
...
}
Sample 1:
var value = 123;//is int
type = property.GetType();// is double
var x = (double)value;//Can be casted
Sample 2:
var value = "asd";//is string
type = property.GetType();// is double
var x = (double)value;//Can not be casted
You can use IsAssignable:
bool isValidCast = type.IsAssignableFrom(value.GetType())
As per the comments about int to double:
I've made a mistake in my comment, so i deleted it.
int can be implicitly converted to double because there is a predefined implicit conversion, see here
There are many ways to convert or cast from type to type. For example, You can use implicit/explicit conversion, you can use TypeConverter or implement the IConvertible interface.
Now, you have to decide which use case is relevant to you. It can be a bit complex to check them all, especially without knowing the destination type at design time.
In your code snippet, type is a variable of type Type, hence why it is throwing that error. You can change your code to use Convert.ChangeType() instead. Something like this:
var value = Reader[item];
PropertyInfo property = properties.Where(x => x.Name == item).FirstOrDefault();
var type=property.PropertyType;
object cs= Convert.ChangeType(value, type);
if (cs!=null){
...
}
Notice that, since you don't know the strong type of your property at compile time, you still have to box it into an object type after changing its type. This means you wouldn't be able to access its properties and methods directly using dot syntax in code (e.g. cs.MyProperty). If you wish to be able to do that, you can use the dynamic type in C#:
dynamic dcs = cs;
Console.Write(dcs.MyProperty);
When using Convert.ChangeType() you have to make sure you are converting to the correct type. E.g.:
if (value.GetType() == type)
{
object cs= Convert.ChangeType(value, type);
}

Object does not match target type PropertyInfo SetValue - one class to another

So I have 2 classes, both have identical Property names. One class contains different variables: int, strings, bool and DateTime The second class contains only 1 int and the rest are all strings.
Now I want to loop through all the properties, get the value from class1, encrypt that data and save it as a string in obj2, then return it to the main form (to save it in a database later).
public PersoonEncrypted EncryptPersonClass(Class1 object1)
{
PersoonEncrypted persEncrypt = new PersoonEncrypted(); //second class obj
Type type = object1.GetType();
PropertyInfo[] properties = type.GetProperties();
Type type2 = persEncrypt.GetType();
PropertyInfo[] properties2 = type.GetProperties();
foreach (var bothProperties in properties.Zip(properties2, (obj1, obj2) => new { Obj1 = obj1, Obj2 = obj2 }))
{
string value = "";
value = bothProperties.Obj1.GetValue(object1) as string;
if (!string.IsNullOrWhiteSpace(value))
{
string encryptValue = Encrypt(value);
if ((bothProperties.Obj2 != null) && (bothProperties.Obj2.PropertyType == typeof(string)))
{ //!= null check has no effect at all
bothProperties.Obj2.SetValue(persEncrypt, encryptValue, null); //errorLine
}
}
}
return persEncrypt;
}
That is what I came up with until now.
I have, of course, searched for other solutions like this one. This, after applying some own changes, didn't return any errors, but it didn't save any encrypted strings into the class persEncrypt. What I concluded was, from that test, is that it was testing if the value in the second class(persEncrypt in my example) from the particular property was null, while it shouldn't do that, it should make a new instance of that variable and save it in the object class, but removing that check gave me the same error.
you're just .Zip-ing the two lists of PropertyInfo objects, which simply iterates through both lists and doesn't check or sort for any sort of matching. This could result in erroneous behavior depending on the order in which properties appear - consider using a .Join instead to match property names.
This code doesn't check for an indexer on the property before attempting to assign to it without one - any indexed property which is of type string will make it to this point and then throw an exception when you try to set it.
Because this code is calling into Properties, there's the possibility an exception is being thrown by the code of the Property itself. This is where a StackTrace from your exception could reveal much more about what's happening.
Your code also checks for a property of type string directly - when using reflection you should use IsAssignableFrom instead in order to allow for inherited types, though that is unlikely the issue in this one case.

Passing properties as parameters to be Got and Set

Well, I need to repeat same code for many properties.
I've seen examples taking Action delegates, but they don't fit quite well here.
I want something like this: (see explanation below)
Dictionary<Property, object> PropertyCorrectValues;
public bool CheckValue(Property P) { return P.Value == PropertyCorrectValues[P]; }
public void DoCorrection(Property P) { P.Value = PropertyCorrectValues[P]; }
.
I want to have a dictionary containing many properties and their respective "correct" values. (I know it's not well declared, but that's the idea). Properties are not necessarely inside my class, some of them are in objects of different assemblies.
A method bool CheckValue(Property). This method must access the actual value of the property and compare to the correct value.
And a method a void DoCorrection(Property). This one sets the property value to the correct value.
Remember I have many of those properties, I wouldn't like to call the methods by hand for each property. I'd rather iterate through the dicionary in a foreach statement.
So, the main question is in the title.
I've tried the by ref, but properties don't accept that.
Am I obligated to use reflection??? Or is there another option (if I need, reflection answer will be accepted as well).
Is there anyway I can make a dictionary with pointers in C#? Or some kind of assignment that changes the value of variable's target instead of changing the target to another value?
Thanks for the help.
You can do this using reflection. Get a list of the properties on the object of interest with typeof(Foo).GetProperties(). Your PropertyCorrectValues property can have type IDictionary<PropertyInfo, object>. Then use the GetValue and SetValue methods on PropertyInfo to perform the desired operations:
public bool CheckProperty(object myObjectToBeChecked, PropertyInfo p)
{
return p.GetValue(myObjectToBeChecked, null).Equals(PropertyCorrectValues[p]);
}
public void DoCorrection(object myObjectToBeCorrected, PropertyInfo p)
{
p.SetValue(myObjectToBeCorrected, PropertyCorrectValues[p]);
}
In addition to Ben's code I'd like to contribute the following code fragment:
Dictionary<string,object> PropertyCorrectValues = new Dictionary<string,object>();
PropertyCorrectValues["UserName"] = "Pete"; // propertyName
PropertyCorrectValues["SomeClass.AccountData"] = "XYZ"; // className.propertyName
public void CheckAndCorrectProperties(object obj) {
if (obj == null) { return; }
// find all properties for given object that need to be checked
var checkableProps = from props
in obj.GetType().GetProperties()
from corr in PropertyCorrectValues
where (corr.Key.Contains(".") == false && props.Name == corr.Key) // propertyName
|| (corr.Key.Contains(".") == true && corr.Key.StartsWith(props.DeclaringType.Name + ".") && corr.Key.EndsWith("." + props.Name)) // className.propertyName
select new { Property = props, Key = corr.Key };
foreach (var pInfo in checkableProps) {
object propValue = pInfo.Property.GetValue(obj, null);
object expectedValue = PropertyCorrectValues[pInfo.Key];
// checking for equal value
if (((propValue == null) && (expectedValue != null)) || (propValue.Equals(expectedValue) == false)) {
// setting value
pInfo.Property.SetValue(obj, expectedValue, null);
}
}
}
When using this "automatic" value correction you might also consider:
You cannot create a PropertyInfo object just by knowing the property name and independently of the declaring class; that's why I chose string for the key.
When using the same property name in different classes then you might need to change the code that is doing the actual assignment because the type between the correct value and the property type might differ.
Using the same property name in different classes will always perform the same check (see point above), so you might need a syntax for property names to restrict it to a specific class (simple dot notation, doesn't work for namespaces or inner classes, but might be extended to do so)
If needed you can replace the "check" and "assign" part with separate method calls, but it might be done inside the code block as stated in my example code.

Efficient way of initializing a generic class' fields and/or properties

I am writing a ConfigParser class, which reads from a config file structured like this:
[Section]
option1 = foo
option2 = 12
option3 = ;
...
The information read is actually stored in a Dictionary<string, string>. What i'd like to achieve is the following:
struct ConfigStruct
{
public string option1;
public int option2;
public char option3 { get; set; }
// Any other _public_ fields or properties
}
ConfigParser Cp = new ConfigParser("path/to/config/file"); // Loads content
ConfigStruct Cs = Cp.CreateInstance<ConfigStruct>("Section");
Console.WriteLine(Cs.option1); // foo
Console.WriteLine(Cs.option2.ToString()); // 12
Console.WriteLine(Cs.option3.ToString()); // ;
The struct (or class, it doesn't matter) ConfigStruct, is application-specific, and the ConfigParser class should know nothing about it. Basically, I want to parse the value from a specific option, and store it into the field/property with the same name. Parsing should be done according to the field/property type.
I've developed a stub method for it:
public T CreateInstance<T>(string Section) where T : new()
{
// Gets options dictionary from loaded data
Dictionary<string, string> Options = this.Data[Section];
T Result = new T();
Type StructType = Result.GetType();
foreach (var Field in StructType.GetFields())
{
if (!Options.ContainsKey(Field.Name))
continue;
Object Value;
if (Field.FieldType == typeof(bool))
Value = Boolean.Parse(Options[Field.Name]);
else if (Field.FieldType == typeof(int))
Value = Int32.Parse(Options[Field.Name]);
else if (Field.FieldType == typeof(double))
Value = Double.Parse(Options[Field.Name]);
else if (Field.FieldType == typeof(string))
Value = Options[Field.Name];
else if (Field.FieldType == typeof(char))
Value = Options[Field.Name][0];
// Add any ifs if needed
else { /* Handle unsupported types */ }
Field.SetValue(Result, Value);
}
foreach (var Property in StructType.GetProperties())
{
// Do the same thing with public properties
}
return Result;
}
Do you think this is the right approach to the problem? Or should I move the responsability of initializing the struct to the application logic instead of the ConfigParser class? I know it's more efficient, but using reflection I write this method only once, and works for every struct.
Should I use reflection to invoke Parse() so that I can avoid all those ifs? Or you'd rather make those conversions type by type, to prevent unexpected behaviour?
Thanks for your time.
Assuming there is a specific reason why you are not using app.config/web.config or other built-in configuration files.
I think this comes down to what the rest of the application is doing, but personally I would do it this way. It allows you to get the return type cleanly and you are not passing an extra stuct down the stack that you don't need to be.
Reflection is a fantastic tool but has some overhead so if the list of types is finite then specifying them manually is more efficient, or alternately only reflecting the unknown types. Also I would change your if blocks to a switch statement, you will gain efficiencies if the IL complier can fully optimise the condition block.
I think there is a simpler solution. You could use a custom section handler to store your settings, custom section handlers are well described here: http://devlicio.us/blogs/derik_whittaker/archive/2006/11/13/app-config-and-custom-configuration-sections.aspx).

Testing if an Object is a Dictionary in C#

Is there a way to test if an object is a dictionary?
In a method I'm trying to get a value from a selected item in a list box. In some circumstances, the list box might be bound to a dictionary, but this isn't known at compile time.
I would like to do something similar to this:
if (listBox.ItemsSource is Dictionary<??>)
{
KeyValuePair<??> pair = (KeyValuePair<??>)listBox.SelectedItem;
object value = pair.Value;
}
Is there a way to do this dynamically at runtime using reflection? I know it's possible to use reflection with generic types and determine the key/value parameters, but I'm not sure if there's a way to do the rest after those values are retrieved.
Check to see if it implements IDictionary.
See the definition of System.Collections.IDictionary to see what that gives you.
if (listBox.ItemsSource is IDictionary)
{
DictionaryEntry pair = (DictionaryEntry)listBox.SelectedItem;
object value = pair.Value;
}
EDIT:
Alternative when I realized KeyValuePair's aren't castable to DictionaryEntry
if (listBox.DataSource is IDictionary)
{
listBox.ValueMember = "Value";
object value = listBox.SelectedValue;
listBox.ValueMember = ""; //If you need it to generally be empty.
}
This solution uses reflection, but in this case you don't have to do the grunt work, ListBox does it for you. Also if you generally have dictionaries as data sources you may be able to avoid reseting ValueMember all of the time.
It should be something like the following. I wrote this in the answer box so the syntax may not be exactly right, but I've made it Wiki editable so anybody can fix up.
if (listBox.ItemsSource.IsGenericType &&
typeof(IDictionary<,>).IsAssignableFrom(listBox.ItemsSource.GetGenericTypeDefinition()))
{
var method = typeof(KeyValuePair<,>).GetProperty("Value").GetGetMethod();
var item = method.Invoke(listBox.SelectedItem, null);
}
I know this question was asked many years ago, but it is still visible publicly.
There were few examples proposed here in this topic and in this one:
Determine if type is dictionary [duplicate]
but there are few mismatches, so I want to share my solution
Short answer:
var dictionaryInterfaces = new[]
{
typeof(IDictionary<,>),
typeof(IDictionary),
typeof(IReadOnlyDictionary<,>),
};
var dictionaries = collectionOfAnyTypeObjects
.Where(d => d.GetType().GetInterfaces()
.Any(t=> dictionaryInterfaces
.Any(i=> i == t || t.IsGenericType && i == t.GetGenericTypeDefinition())))
Longer answer:
I believe this is the reason why people make mistakes:
//notice the difference between IDictionary (interface) and Dictionary (class)
typeof(IDictionary<,>).IsAssignableFrom(typeof(IDictionary<,>)) // true
typeof(IDictionary<int, int>).IsAssignableFrom(typeof(IDictionary<int, int>)); // true
typeof(IDictionary<int, int>).IsAssignableFrom(typeof(Dictionary<int, int>)); // true
typeof(IDictionary<,>).IsAssignableFrom(typeof(Dictionary<,>)); // false!! in contrast with above line this is little bit unintuitive
so let say we have these types:
public class CustomReadOnlyDictionary : IReadOnlyDictionary<string, MyClass>
public class CustomGenericDictionary : IDictionary<string, MyClass>
public class CustomDictionary : IDictionary
and these instances:
var dictionaries = new object[]
{
new Dictionary<string, MyClass>(),
new ReadOnlyDictionary<string, MyClass>(new Dictionary<string, MyClass>()),
new CustomReadOnlyDictionary(),
new CustomDictionary(),
new CustomGenericDictionary()
};
so if we will use .IsAssignableFrom() method:
var dictionaries2 = dictionaries.Where(d =>
{
var type = d.GetType();
return type.IsGenericType && typeof(IDictionary<,>).IsAssignableFrom(type.GetGenericTypeDefinition());
}); // count == 0!!
we will not get any instance
so best way is to get all interfaces and check if any of them is dictionary interface:
var dictionaryInterfaces = new[]
{
typeof(IDictionary<,>),
typeof(IDictionary),
typeof(IReadOnlyDictionary<,>),
};
var dictionaries2 = dictionaries
.Where(d => d.GetType().GetInterfaces()
.Any(t=> dictionaryInterfaces
.Any(i=> i == t || t.IsGenericType && i == t.GetGenericTypeDefinition()))) // count == 5
you can check to see if it implements IDictionary. You'll just have to enumerate over using the DictionaryEntry class.
I'm coming from Determine if type is dictionary, where none of the answers there adequately solve my issue.
The closest answer here comes from Lukas Klusis, but falls short of giving a IsDictionary(Type type) method. Here's that method, taking inspiration from his answer:
private static Type[] dictionaryInterfaces =
{
typeof(IDictionary<,>),
typeof(System.Collections.IDictionary),
typeof(IReadOnlyDictionary<,>),
};
public static bool IsDictionary(Type type)
{
return dictionaryInterfaces
.Any(dictInterface =>
dictInterface == type || // 1
(type.IsGenericType && dictInterface == type.GetGenericTypeDefinition()) || // 2
type.GetInterfaces().Any(typeInterface => // 3
typeInterface == dictInterface ||
(typeInterface.IsGenericType && dictInterface == typeInterface.GetGenericTypeDefinition())));
}
// 1 addresses public System.Collections.IDictionary MyProperty {get; set;}
// 2 addresses public IDictionary<SomeObj, SomeObj> MyProperty {get; set;}
// 3 (ie the second .Any) addresses any scenario in which the type implements any one of the dictionaryInterfaces Types.
The issues with the other answers - assuming they address #3 - is that they don't address #1 and #2. Which is understandable, since getting and checking a Property's Type probably isn't a common scenario. But in case you're like me, and that scenario is part of your use-case, there you go!
You could be a little more generic and ask instead if it implements IDictionary. Then the KeyValue collection will contina plain Objects.
I believe a warning is at place.
When you're testing if an object 'is a' something this or that, you're reimplementing (part of) the type system. The first 'is a' is often swiftly followed by a second one, and soon your code is full of type checks, which ought to be very well handled by the type system - at least in an object oriented design.
Of course, I know nothing of the context of the question. I do know a 2000 line file in our own codebase that handles 50 different object to String conversions... :(
if(typeof(IDictionary).IsAssignableFrom(listBox.ItemsSource.GetType()))
{
}

Categories

Resources