torsdag 27 mars 2008

Use Extensions Methods to create those methods you always wanted...

With C# 3.0 and Visual Studio 2008 Microsoft gave us the power to extend existing classes with our own methods without doing any inheritance, partial classes etc.

This is done using virtual classes and virtual methods together with the new "this" keyword. Example:
namespace myExtensions
{
public static class Extensions
{
   public static int ParseToInt(this string s)
   {
      return int.Parse(s);
   }
}
}


We can now use this method:
string s = "123";
int i = s.ParseToInt();


As you can imagine this is a fantastic feature as we can create our own library of useful methods. One specific method that I've been missing is a generic way to obtain a control in the Repeater ItemDataBound event:
protected void myRepeater_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
   if (e.Item.ItemType == ListItemType.AlternatingItem || e.Item.ItemType == ListItemType.Item)
   {
      ((Literal)e.Item.FindControl("myLiteral")).Text = "Something...";
   }
}


We can now create two useful extensions:
//Method to check whether the current RepeaterItem is of itemType "Item" or "AlternatingItem"
public static bool IsContentItem(this RepeaterItem item)
{
   return (item.ItemType == ListItemType.AlternatingItem || item.ItemType == ListItemType.Item);
}

//Method to retrieve a control from the RepeaterItem
public static T FindControl<T>(this RepeaterItem item, string id) where T : Control
{
   return item.FindControl(id) as T;
}


Usage:
protected void myRepeater_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.IsContentItem())
{
   e.Item.FindControl<Literal>("myLiteral").Text = "Something...";
}
}


Pretty nice huh? :)

fredag 14 mars 2008

Decimal type; howto control the decimal output

Formatting a decimal value to display only the applicable number of decimals might not seem to be an easy thing if you are using only the "ToString" method.

Example:
decimal d1 = decimal.Parse("100.510");
decimal d2 = decimal.Parse("100.00");
decimal d3 = decimal.Parse("100.50");


Lets say you want to output the value just with its applicable number of decimals, ie #1 = 2 decimals, #2 = 0 decimals and #3 = 1 decimal.

To do this, you definitely do not need to use any string formatting or such, instead simply use the ToString method with the the following format: "G29".
The solution is really simple and has been around since .NET 1.0.

Example:
d1.ToString("G29"); //100.51
d2.ToString("G29"); //100
d3.ToString("G29"); //100.5

onsdag 12 mars 2008

Using an anonymous type outside its scope

With C# 3.0, Microsoft introduced "Anonymous Types" which gives us the ability to create new types in runtime.

Example:
var x = new {Name = "Fredrik", Country = "Sweden"};
x.Name = "New Name";


As you can see, object X is assigned to a new type where the properties are created in runtime. Each property type is interpreted by the assigned value which means that we still have type safety.

The anonymous type is however only available in the current scope, ie in the current method, if-statement etc. This is fine, as we normally do not want to expose the type to external code as this code does not know anything about the new type or its properties.

There are however occasions where we might need the anonymous type outside the scope. Lets say within an ASP.NET Page where you bind a control (eg. Repeater) to a list of anonymous types. Example:

IEnumerable orders = GetOrders(); //get list of orders
IEnumerable orderLines = GetOrderLines(); //get another list of order lines

//create new list based on orders and orderLines
var list = from order in orders
join orderLine in orderLines on o.OrderId equals orderLine.OrderId
select new {Customer = o.CustomerName, LineAmount = orderLine.Amount};

//create a delegate method to handle the ItemDataBound event
this.repeaterOrders.ItemDataBound += new RepeaterItemEventHandler(repeaterOrders_ItemDataBound);

//bind the repeater
this.repeaterOrders.DataSource = list;
this.repeaterOrders.DataBind();


Now, in the method for "ItemDataBound" we want to cast the DataItem to the Anonymous type to be able to use it for the Repeater output.
We can do this be creating a new generic method that casts the object to the anonymous type.


private T Cast<t>(object o, T type)
{ return ( T )o; }


Using this in the code, looks like the following:


protected void repeaterOrders_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item e.Item.ItemType == ListItemType.AlternatingItem)
{

//cast the "DataItem" property into the anonymous type
var x = Cast(e.Item.DataItem, new {Customer="", LineAmount=0});

//use the x object with ites properties based on the anonymous type
totalAmount+= x.LineAmount;

}
}


As you can see, the "client" using the Cast method must know the internal structure of the anonymous type. This is not a very nice solution when passing data between different layers, but when used in the same ASP.NET page or class I feel that it is a quite nice solution to solve the problem. And in the end...that's what really matters.