The Code Slinger

December 17, 2007

Custom XML Serialization with LINQ

Filed under: C#,LINQ,Reflection,XLINQ — Pete @ 11:24 pm

Wouldn’t it be nice if you could automatically serialize into XML not only the structure of any class in your business framework, but the actual values at runtime of each instance? This could be used for additional logging to an offsite service, re-hydrating objects at a later time, or simply a form of custom serialization without all the overhead the native XMLSerializer has built into it.

Previously I had this type of code implemented as an interface, so that each object could serialize itself if necessary.  This was cumbersome and while in theory one might want a different XML structure per business object, typically in my uses I found that each object just needed to output the direct data it held.   So using the new 3.5 framework features like LINQ & XLINQ, let’s take a look at what a custom serializer might look like (full source is posted at the end of the article as usual).

public static class Serializer<T> where T: class, new()

{

    private static Dictionary<Type, PropertyInfo[]> props =

        new Dictionary<Type, PropertyInfo[]>();

}

First, our class will be a generic implementation, so that we can pass in any of our business entity objects.  Inside we have a static member which is simply a container for keeping track of our PropertyInfo arrays based on class type.  This keeps us, over time, from having to duplicate reflection calls unnecessarily.

public static string Serialize(T instance)

{

    Type t = typeof(T);

    PropertyInfo[] pis = null;

    lock (props)

    {

        if (!props.TryGetValue(t, out pis))

        {

            PropertyInfo[] ps = t.GetProperties(

                BindingFlags.Public |

                BindingFlags.GetProperty |

                BindingFlags.Instance);

            props.Add(t, ps);

        }

        pis = props[t];

    }

 

    XElement xd = new XElement(t.Name);

    pis.ForEach(p =>

    {

        object val = null;

        PropertyCaller<T>.GenGetter g =

            PropertyCaller<T>.CreateGetMethod(p);

        val = g(instance);

        if (val == null)

            val = “null”;

        XAttribute xa = new XAttribute(p.Name, val);

        xd.Add(xa);

    });

 

    return xd.ToString();

}

Here our Serialize method takes as input an instance of the type we are serializing. It converts the Type data, and then looks in our container to see if we have already serialized one of these previously.  If not, it gets the necessary PropertyInfo data from the Type and inserts it for future use into our container. 

Next we use the XElement class to create a new xml node named after our class type.  You could use any data you want from the class, I just chose to use the Name property.  Now, we use the extension method ForEach<T> of the PropertyInfo array to execute a lambda expression.  This expression basically just uses the PropertyCaller<T> class we created previously to get the delegate “getter” for each property on the class.  Calling this delegate will retrieve the value of the property for the instance we are serializing.  Then I simply use the name of the property and it’s value to create an XAttribute to decorate the XElement for our object.

The return value of the Serialize method is simply the string output of our XElement object in XML.

Now let’s look at how to take that string XML and turn it back into our object.

public static T Deserialize(XElement xd)

{

    Type t = typeof(T);

    PropertyInfo[] pis = null;

    lock (props)

    {

        if (!props.TryGetValue(t, out pis))

        {

            PropertyInfo[] ps = t.GetProperties(

                BindingFlags.Public |

                BindingFlags.SetProperty |

                BindingFlags.Instance);

            props.Add(t, ps);

        }

        pis = props[t];

    }

    IEnumerable<XAttribute> ix = xd.Attributes();

 

    T lilt = new T();

    pis.ForEach(p =>

    {

        string propname = p.Name;

        var att = (from xat in ix

                   where xat.Name.LocalName == p.Name

                   select xat).FirstOrDefault();

        if(att != null)

        {

            PropertyCaller<T>.GenSetter s =

                PropertyCaller<T>.CreateSetMethod(p);

            object val = Converter(p.PropertyType, att.Value);

            s(lilt, val);

        }

    });

    return lilt;

}

Our Deserialize method takes an XElement instance which represents the data for a particular instance of T.   You could also take plain string XML and load it into the XElement if you wanted, via the XElement.Parse() method.

Again, we get our PropertyInfo array so we know how to match up the XAttributes, then again using the ForEach<T> extension method, we provide a lambda expression (anonymous method) implementation which determines which XAttribute of the XElement node matches up with each property name.  Notice the LINQ query on the results of the Attributes() method off of the XElement object.  Since the results are of type IEnumerable<T>, we know that we can query them using LINQ.   In this case we simply find the FirstOrDefault (null if one doesn’t exist) value in the query in which the LocalName of the XAttribute matches our property name. 

Now if we have a matching attribute for the property, we again use our PropertyCaller<T> implementation to get the delegate “setter” for the property.  Calling this delegate with the value of our attribute, we are able to set the value of our object for the property specified.

The Converter method is simply a helper method to allow us to properly convert the string representation of the value stored in the XML into an actual object type based on the property’s type. 

public static object Converter(Type t, string value)

{

    object retval = null;

    string checkType = string.Empty;

    bool valueset = false;

    if (t.IsGenericType)

    {

        checkType = t.GetGenericArguments()[0].FullName;

        if (value == “null”)

        {

            valueset = true;

            retval = null;

        }

    }

    else

        checkType = t.FullName;

 

    if (!valueset)

    {

        switch (t.FullName)

        {

            case “System.Int32”:

                retval =

                    new Int32Converter().ConvertFrom(value);

                break;

            case “System.Double”:

                retval =

                    new DoubleConverter().ConvertFrom(value);

                break;

            case “System.Decimal”:

                retval =

                    new DecimalConverter().ConvertFrom(value);

                break;

            case “System.Boolean”:

                retval =

                    new BooleanConverter().ConvertFrom(value);

                break;

            case “System.DateTime”:

                retval =

                    new DateTimeConverter().ConvertFrom(value);

                break;

            default:

                retval = value;

                break;

        }

    }

    return retval;

}

The only real gotcha with this is that you have to implement a conversion routine (I use TypeConverters) for each type you are storing in your classes.  Typically this is limited to a relatively small set of types (mostly value types).  This particular implementation handles generic “nullable” versions of each value type listed.  In the XML serialization routine, null values are explicitly spelled out as “null”. 

Anyway, the sample project should give you a pretty clear understanding of how to put all this together.  Hopefully this has shown how to not only accomplish a potentially system-wide task with relatively little code, but how to build upon the dynamic method invocation code we put together previously in a real-world scenario.

Til next time…keep on slangin!

————————————————

Example Project Source

November 20, 2007

LINQ to Objects: Nested Queries

Filed under: .NET,LINQ,VB.NET — Pete @ 6:21 pm
Tags: , ,

LINQ allows us to query our object tree(s) in a much easier and more readable manner than using traditional looping/iteration mechanisms of the past.

In this example, I have a Role object which contains a Dictionary(Of Type, List(Of IPermission)) which stores a series of object types as it’s key and a list of permission objects (which implement the IPermission interface). This keeps track of the relationship(s) between roles and permissions.

In the past, I would have written a function which takes a particular characteristic of one permission in particular and returns that permission type as the following:

 

253 Public Function InheritedStatusesByType(ByVal a_TypeEnum As WorkObjectTypeEnum) As IEnumerable(Of Status) 254 Dim hshReturn As New Dictionary(Of Integer, Status)

255 256 For Each rl As Role In CurrentRole.GetPermissionDL(Of Role)() 'ChildrenRolesDirect

257 For Each st As Status In rl.GetPermissionFlat(Of Status)() 'Statuses 258 If st.WorkObjectTypeEnum = a_TypeEnum Then

259 If Not hshReturn.ContainsKey(st.ID) Then 260 hshReturn.Add(st.ID, st)

261 End If 262 End If

263 Next 264 Next

265 Return New List(Of Status)(hshReturn.Values) 266 End Function

So this loops through the children roles (roles can be nested in this security system) that are direct children, then for each one it gets the list of all statuses which are either directly set or inherited from further sub-roles.

It inspects each status to be sure it’s of the type we want (via the enum), then it checks the return dictionary to make sure we don’t already have the status, add it if necessary, and once the loops exit successfully, the return values of the dictionary are cast into a return list of unique statuses the current Role object has access to.

This isn’t too bad, but it certainly isn’t all that intuitive to the regular programmer. One has to take a few minutes to “wrap ones head” around what is going on. More time spent on that is less time adding features or new functionality.

So, I’ve rewritten this type of code using LINQ. It goes something like…..

 

244 Public Function InheritedStatusesByType(ByVal a_TypeEnum As WorkObjectTypeEnum) As IEnumerable(Of Status) 245 'Try with LINQ

246 Dim ret = From rl In _ 247 m_CurrentRole.GetPermissionDL(Of Role)(), _

248 st In rl.GetPermissionFlat(Of Status)() _ 249 Where st.WorkObjectTypeEnum = a_TypeEnum _

250 Select st 251

252 Return ret 253 End Function

So far so good. This does basically the same thing using LINQ style query syntax. However the only issue with this is that it can potentially return duplicate statuses. This is because like in normal SQL, it is effectively doing a join on the detail records, and if more than one sub-role has access to the same status, it will be returned multiple times.

So, we need to figure out a way to do the equivalent of “DISTINCT” in SQL. Looking in the documentation one finds just that.

 

244 Public Function InheritedStatusesByType(ByVal a_TypeEnum As WorkObjectTypeEnum) As IEnumerable(Of Status) 245 'Try with LINQ

246 Dim ret = (From rl In _ 247 m_CurrentRole.GetPermissionDL(Of Role)(), _

248 st In rl.GetPermissionFlat(Of Status)() _ 249 Where st.WorkObjectTypeEnum = a_TypeEnum _

250 Select st).Distinct() 251

252 Return ret 253 End Function

The only problem is that when I run this with my example code, I still get duplicates. Hmmmm. Digging further into the Distinct syntax, I find that it’s default implementation uses the method GetHashCode() to determine equality. Obviously this won’t work, as our objects are distinct instances even if their data is the same. We need a way of overriding the Distinct logic without losing our readability.

This is where we find out about Extension Methods.

Here’s the code for the extension method we need to write to accomplish our own Distinct implementation:

 

9 <Extension()> _ 10 Public Function Distinct(Of T As PersistLoad)(ByVal source As IEnumerable(Of T)) As IEnumerable(Of T)

11 Return System.Linq.Enumerable.Distinct(source, New IDComparer(Of T)()) 12 End Function

Our source object is simply the same type that we want to write the extension off of (since that is the “type” we’re doing the Distinct operation on). However the second parameter is a custom class which implements the IEqualityComparer(Of T) interface, effectively defining how two objects (in this case inheriting from the base type PersistLoad) are defined as being “equal”.

 

2 Public Class IDComparer(Of T As PersistLoad) 3 Implements IEqualityComparer(Of T)

4 5 Public Function Equals1(ByVal x As T, ByVal y As T) As Boolean Implements System.Collections.Generic.IEqualityComparer(Of T).Equals

6 Return x.ID = y.ID 7 End Function

8 9 Public Function GetHashCode1(ByVal obj As T) As Integer Implements System.Collections.Generic.IEqualityComparer(Of T).GetHashCode

10 Return obj.ID.GetHashCode() 11 End Function

12 End Class

In this case, all PersistLoad objects have a property called “ID” which defines it’s key or unique value. You could use any attribute to define equality in reality though.

So, implementing our extension method of the Distinct(Of T as PersistLoad) method and our custom comparer class which it uses, we can retry our LINQ query in our Role object. NOTE that we could literally write any number of Distinct extension methods, which because of the nature of polymorphism, will get called based on the calling type at runtime. In our case, the LINQ query is returning an IEnumerable(Of T as PersistLoad), therefore when calling Distinct on it, our extension method written for that context will be called rather than the default.

 

244 Public Function InheritedStatusesByType(ByVal a_TypeEnum As WorkObjectTypeEnum) As IEnumerable(Of Status) 245 'Try with LINQ

246 Dim ret = (From rl In _ 247 m_CurrentRole.GetPermissionDL(Of Role)(), _

248 st In rl.GetPermissionFlat(Of Status)() _ 249 Where st.WorkObjectTypeEnum = a_TypeEnum _

250 Select st).Distinct() 251

252 Return ret 253 End Function

So our final code (after the extension and comparer implementation) looks exactly the same as before. Now when we run this, no matter how many times a status shows up in the object tree of roles, it will only be returned a single time to the variable ret, which houses a custom iterator ultimately representing an IEnumerable(Of Status) that actually ends up being a List(Of Status) because of the underlying data structures.

Technorati Tags: , ,

Extension Methods in Action

Filed under: .NET,LINQ,VB.NET — Pete @ 3:54 am
Tags: , ,

Extension methods are a new language feature in C# and VB.NET which in essence is one of the underpinnings of the new LINQ (Language INtegrated Query) syntax new to .NET.

At first look, extension methods seem to “add” functionality to existing types. But in reality they simply allow you the flexibility of making static method calls more intuitive within the framework of your code by allowing you to attach those methods to existing types (which you may or may not have the source-code to).

As an example, I’ve taken a common task that I find myself doing in my code quite a bit. Having a generic List(Of T) of business objects, I want to find the one object in that list that has a particular ID.

27 Public Shared Function GetByID(Of T As PersistLoad)(ByVal a_List As List(Of T), ByVal a_ID As Integer) As T

28 Dim current As T = Nothing

29 For Each obj As T In a_List

30 If obj.ID = a_ID Then

31 current = obj

32 Exit For

33 End If

34 Next

35

36 Return current

37 End Function

Using this generic implementation, I can pass in any list of objects, the ID I want to search for, and either return an object of type T or nothing/null. This works fine, however if I want to do the same for another data type, e.g. like a Dictionary, I have to write a new method that knows how to iterate over that type of object.

The calling code for this implementation would be something like:

112 m_CurrentBarcode = ExtensionsRegular.GetByID(m_Barcodes, a_BarcodeID)

Notice that I have to pass in as an input parameter the actual list of objects (in this case, barcodes)? Additionally, the method is simply called from a static/shared method repository class called ExtensionsRegular.

Now, let’s look at how an extension method can help us here.

7 <Extension()> _

8 Public Function FindByID(Of T As PersistLoad)(ByVal list As IEnumerable(Of T), ByVal a_ID As Integer) As T

9 Dim selected = _

10 From b In list _

11 Where b.ID = a_ID _

12 Select b

13

14 If selected.Count > 0 Then

15 Return selected.First()

16 Else

17 Return Nothing

18 End If

19 End Function

Notice with the extension method implementation, we can use the IEnumerable generic interface as the input. We’ll come back to why that’s important in a minute. Inside the implementation of the extension method, we are using a LINQ query that selects from the list (which must implement IEnumerable or it’s generic equivalent IEnumerable) where the ID equals the a_ID parameter we passed in. Notice 1) how similar this is to SQL queries and 2) how natural it looks to the reader in terms of what is actually being done in the code.

Now our calling code looks like:

114 m_CurrentBarcode = m_Barcodes.FindByID(a_BarcodeID)

Because it’s an extension method, the compiler actually allows the method to be called as if it were an instance member method. Notice that the only input parameter is the ID we’re searching for.

Additionally, since we used the IEnumerable(Of T) interface as our input declaration, we can now use this exact same extension method if we were trying to FindByID on basically ANY type (in the .NET framework or otherwise) which implements IEnumerable(Of T), since any IEnumerable type must implement the MoveNext() method.

Blog at WordPress.com.