Showing posts with label C#. Show all posts
Showing posts with label C#. Show all posts

Tuesday, May 5, 2009

Dynamic Expression

Scott Gu has a good article about a great sample component called Dynamic Linq. This is a very powerful addition to your linq toolkit which lets you create expressions based on strings. So imagine that you want to add sorting to a grid which is bound to a List. One way would be to have a switch statement for each options (Yes you can throw up I'll wait).

Another way would be to use the dynamic query library. I've always wondered how difficult it would be to create an Expression dynamically. This would be a nice addition to my Audit Logger allowing for the configuration of an audit category to exist outside of the code.

Much of this code came from this stackoverflow.com article. I simply went and added the glue:


        public static IEnumerable<T> Sort<T>(this IEnumerable<T> source,

            string sortExpression, bool desc)

        {

            var param = Expression.Parameter(typeof(T), string.Empty);

 

            var fields = sortExpression.Split('.');

            Expression property = null;

            Expression parentParam = param;

            foreach (var field in fields)

            {

                property = Expression.Property(parentParam, field);

                parentParam = property;

 

            }

 

            var sortLambda = Expression.Lambda<Func<T, object>>(

                Expression.Convert(property, typeof(object)),

                param);

 

            if (desc)

            {

                return source.AsQueryable<T>().OrderByDescending<T, object>(sortLambda);

            }

 

            return source.AsQueryable<T>().OrderBy<T, object>(sortLambda);

        }



Basically this will give you an expression which returns the value of a property. It will support property / field invocation so myObject.MyField.MyProperty. It works by creating an expression which represents the type of parameter being pased in to the lambda.

Then it builds an expression tree by chaining new expressions together for each token myObject, myField etc. Finally it creates a lambda which can be executed.

Thursday, March 19, 2009

Dynamically call a Generic method using Reflection

While working on a request to make the Database Logging add-on I discussed previously, I came accross an interesting problem.

I wanted to be able to define the name of the ExpressionGroup, stored procedure and connection to use when logging to the database in a config file. I figure this was the first step in enabling configuration to the system. In order to do this I needed to create an instance of Expression<T>.

The expression cache already has a CreateGroup<T>() method which I wanted to use. So how can I call this method if I don't know the type of T until runtime? Its actually very easy.

Essentially you want to get a reference to the Method via Reflection. There are lots of ways to do this. Once you have a MethodInfo class, you can call MakeGenericMethod which takes a parameter array of type objects. It will use these type objects to subsitute in place for the Generic type T.

At this point you can call the method just like any other method via reflection, using the Invoke() method on MethodInfo. The code looks like this:



var meth = this.GetType().GetMethod("CreateGroup");


var genericMeth=meth.MakeGenericMethod(getType(grpConfig.AuditLogEntryType));


IAuditLoggerExpressionGroup expGroup = (IAuditLoggerExpressionGroup)genericMeth.Invoke(this, new object[] { grpConfig.Name, grpConfig.ConnectionName, grpConfig.Procedure });


this.Add(expGroup);





That's all there is to it.

Wednesday, March 11, 2009

Extension Methods & Null Objects

I ran into an issue that I had learned about a while ago but the code that I was working on predated this. I find it interesting enough to share. I love the various predicate / action methods on List<T> that allows you to interact with a list by passing in a delegate.

I've always been a little dissapointed that these methods aren't part of the IList<T> interface; however, with Extension methods we can rectify this. I defined a new method in a static class as:

        public static T Find<T>(this IList<T> col, Predicate<T> match)

        {

            if (match == null)

            {

                throw new ArgumentNullException("match");

            }

 

            for (int i = 0; i < col.Count; i++)

            {

                if (match(col[i]))

                {

                    return col[i];

                }

            }

            return default(T);

        }



This has been working fine for almost a year now, until today when I got a null Reference exception on the for loop. The interesting thing with Extension methods is they are nothing more then a static method that the compiler does some magic with.

To prove this go ahead and create a simple console application. Add an extension method on your favorite type (I choose a string), and call this from your main method. Here's what I used:

    static class Extensions

    {

        public static void ToMe(this string value)

        {

            if (value == null)

            {

                Console.WriteLine("Null value");

            }

        }

    }



static void Main(string[] args)

        {

            string s = null;

            s.ToMe();

            Console.ReadLine();

        }



After you compile this go ahead and fire up reflector or Ildasm and have a look at the IL. In my case I had the following instruction:
call void ConsoleApplication4.Extensions::ToMe(string)


Since all we are doing is calling a static method and passing in a reference to the variable which the extension method was called off of, it becomes perfectly legal to call extension methods on a null reference.

Now in my opinion this is wrong, and a side effect of the implementation, and we should not rely upon this behavior. The correct code should look like:

       public static T Find<T>(this IList<T> col, Predicate<T> match)

        {

            if (match == null)

            {

                throw new ArgumentNullException("match");

            }

            if (col == null)

            {

                throw new NullReferenceException();

            }

            for (int i = 0; i < col.Count; i++)

            {

                if (match(col[i]))

                {

                    return col[i];

                }

            }

            return default(T);

        }

Tuesday, March 11, 2008

Using the SerializationBinder for versioning

Normally when building an application I am a strong advocate for storing long term persistent data in a relational database such as SQL Server; however, with all things there always exceptions.

I am currently working on an application, that has at its core a complex object graph, with several levels of inheritance, and all sorts of references between the internal objects. At some point in the future I will be storing this object in normalized tables inside SQL server; however, because this project started out as a prototype which was loosely defined, and due to the wide variety of references within this object (And the undefined requirements of what it contains and how it works). I opted to store the object as a blob in the database.

This has been a huge win from a productivity standpoint since we can add all sorts of things to the object without worrying about the persistence tier. The negative of this comes when we want to change something. The .net framework has several hooks in place that help you modify an object which you using binary serialization with. One of these hooks is the SerializationBinder.

The SerializationBinder provides a means for you to do type replacement. Say for example you are building version 1 of an application. You spend hours designing testing and implementing it, and you ship the application, and your customers love the application and start asking for version 2. Unless you are superman you will probably not have designed everything ideally to support the features in version 2 (And if you did drop me a line, I have a job for you!).

I found myself in a similar situation, where I defined an object called MyCompany.Domain.Note. During our version 2 implementation, I realized that this shouldn't be a MyCompany.Domain.Note but instead needs to be a MyCompany.Domain.Widget.Note. So I change the class around, and run the application. This will result in all sorts of SerilizationExceptions since the Serializer is looking for MyCompany.Domain.Note which no longer exists.

This where the SerializationBindercomes into play. The SerializationBinder is an abstract class so you need to define a new class.


using System.Runtime.Serialization;
public class WidgetSerialzationBinder : SerializationBinder
{
public override Type BindToType(string assemblyName, string typeName)
{
}
}


Implementing this class is very simple. In our case we want to make sure anytime we see MyCompany.Domain.Note we replace it with MyCompany.Domain.Widget.Note. Place this code in the BindToType method.


if (typeName.Contains("MyCompany.Domain.Note"))
{
typeName = typeName.Replace("MyCompany.Domain.Note", "MyCompany.Domain.Widget.Note");
}
return Type.GetType(String.Format("{0}, {1}",typeName, assemblyName));


The reason we are using contains/replace on the typeName is that we might know for sure what the typeName should be. For example if you have a List<mycompany.domain.note> you will need to change it to List<mycompany.domain.widget.note>. The actual type name in this case is: System.Collections.Generic.List`1[[MyCompany.Domain.Widget.Note, MyAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]

To use the binder you will need to set the Binder property on your BinaryFormatter. For example:


 public static object Deserialize(byte[] data,SerializationBinder binder)
{
object obj;


MemoryStream streamMemory = new MemoryStream(data);
BinaryFormatter formatter = new BinaryFormatter();

formatter.AssemblyFormat = FormatterAssemblyStyle.Simple;
formatter.Binder = binder;
obj = formatter.Deserialize(streamMemory);
return obj;
}


Enjoy!

Tuesday, January 29, 2008

Calculating a Random Date in C#

I found myself needing to calculate a random date & time btw a given minimum and maximum date. I ended up creating the following function which appears to work very nicely.

internal DateTime CalcDate(DateTime minDate, DateTime maxDate)
{

//This assumes _rand is a private variable of type System.Random. It calculates a new timespan
//that can be added to the minimum date which will create a new date btw
//the min & max
TimeSpan timeSpan = maxDate - minDate;
TimeSpan randomSpan = new TimeSpan((long)(timeSpan.Ticks * _rand.NextDouble()));
return minDate+randomSpan;

}


One thing I ran into which I was not aware of was that while you can add DateTime & a Timespan as such: DateTime + TimeSpan, the reverse is not true, you cannot add TimeSpan+DateTime.

This to makes no sense particulary since addition is supposed to be commuatitive.