10101010101001

0101010101001

Archive for April 2011

Comparing object properties in C#

leave a comment »

I needed today, in my unit tests, a way to compare two objects of the same type, property by property.
In addition to this I needed the following:

    -If the property is a reference type, then go inside it and compare that too, property by property. (Basically deep object property comparison).
    -If the property is IEnumerable, then compare properties of each element inside the IEnumerable.
    -If the elements inside the IEnumerable are themselves IEnumerable then this could go on many levels deep, but this was not on my requirements.
    -I also want the possibility to ignore certain properties in the comparison, such as property which is a delegate (like the Filter property of the PagedCollectionView framework class).
    And of course I would need to know which properties were not equal, so I could show into my assertions.

Obviously this involves some heavy reflection code which I’m sure it would be fun to write if you had the time.
An alternative is to use a free library, with just one class, that does exactly this: http://comparenetobjects.codeplex.com/
Usage is very simple, and supports all kind of useful features which you can see below:

var compareObjects = new CompareObjects()
            {
                CompareChildren = true, //this turns deep compare one, otherwise it's shallow
                CompareFields = false,
                CompareReadOnly = true,
                ComparePrivateFields = false,
                ComparePrivateProperties = false,
                CompareProperties = true,
                MaxDifferences = 1,
                ElementsToIgnore = new List<string>() { "Filter" }
            };
                                                                            
            bool areEqual = compareObjects.Compare(objectA, objectB);
            Assert.IsTrue(areEqual, compareObjects.DifferencesString); //DifferencesString contains exactly what property and what value(s) was different

For Silverlight you do have to remove a couple of line of codes from it, related to DataTable comparison, which don’t exist in silverlight, but it’s easy and only takes a couple of minutes.

Happy Deep Object Comparisons :)

Advertisements

Written by Liviu Trifoi

April 28, 2011 at 6:20 pm

Silverlight stack trace line numbers

with 8 comments

As you probably know, to have stack traces line numbers in a .net app you need pdb files.
In Silverlight though, pdb files don’t get included in the XAP. Even if it was possible to include them you probably wouldn’t want them there because they tend to be huge and you want to have a fast loading web-site.

So what will you do when your client calls you and says he received an error message like the one below?
NullReferenceException
at ChaptersView.ChaptersTree_OnMouseMove
at ChaptersView.GetPreviousCommandButton

After I had a look today at the answer to this question, it became obvious:

Step 1)
In the place you now log or show exceptions to the user, you stop writing a normal stack trace using exception.ToString() or exception.StackTrace.
You should write a stacktrace that includes IL offsets using the code below:

...
catch (Exception exception)
{
            string errorDescription = string.Empty;
            try
            {
                StackTrace st = new System.Diagnostics.StackTrace(ex);
                string stackTrace = "";

                if (st != null)
                {
                    foreach (StackFrame frame in st.GetFrames())
                    {
                        stackTrace = "at " + frame.GetMethod().Module.Name + "." + frame.GetMethod().ReflectedType.Name +
                                     "." + frame.GetMethod().Name + "  (IL offset: 0x" +
                                     frame.GetILOffset().ToString("x") + ")\n" + stackTrace;
                    }
                }
                errorDescription = stackTrace;
            } catch //sometimes there are no stackframes, just use ex.ToString() in those cases
            {
                errorDescription = ex.ToString();
            }
            //do something with error description, like show it to the user or send it to your log server  
}

If we pass the exception that generated the stacktrace in our first example, it will look like:

NullReferenceException
at ChaptersView.ChaptersTree_OnMouseMove (IL offset: 0x44)
at ChaptersView.GetPreviousCommandButton (IL offset: 0x28)

Step 2: Client sends you an exception/log that includes IL offsets
You can use Reflector or IL Disassembler (which comes with visual studio) to find out the piece of code that generated the exception.
I prefer IL Disassembler because Reflector will only show you IL code from those IL offsets, and there’s a large chance you don’t read IL as well as you read C#.

So you have to perform the following steps:
1) Go to start menu and start IL Disassembler
2) Inside IL Disassembler go to File->Open and load the dll (not the XAP) where the exception was thrown. (e.g. …\Release\Client.dll)
3) Go to View->Show source lines
4) Now navigate to the last method that appears in the stacktrace and we look after the IL offset from the stacktrace.
In our example above this is ChaptersView.GetPreviousCommandButton and has offset 0x28

Inside IL Disassembler we will see a mix of C# code and corresponding IL code:

  IL_001c:  brtrue.s   IL_0029
//000193:             {
//000194:                 throw new NullReferenceException(“Test Exception”);
  IL_001e:  ldstr      "Test Exception"
  IL_0023:  newobj     instance void [mscorlib]System.Exception::.ctor(string)
  IL_0028:  throw
//000195:             }
//000196:
//000197:             var previousCommandButton =
 

As you can see, at IL_0028 there’s the instruction that caused the exception.
This is IL code, but because we’ve checked “View->Show source lines” we also get the corresponding C# code just a few lines above.

//000193: {
//000194: throw new NullReferenceException();

So, in this case the exception was thrown because I’ve thrown it explicitly in order to show how IL offsets and IL Disassembler can be used to get an alternative to stack trace line numbers in silverlight.

Also please don’t just put that piece of code in every catch block. Create a method like “string GetStackTraceFromException(Exception ex)”
Another good idea would be to have some centralized error service, on the server side. You would then send those exception descriptions automatically along with method parameter values logged with PostSharp, whenever an error happens.
So by the time the client calls you, you have fixed the problem and he’s impressed ;)

Happy Debugging.

Written by Liviu Trifoi

April 21, 2011 at 6:15 pm