Home ::  Admin

chris carter's web log

Pluck Me!

1:41 PM Thursday Sep 27, 2007 Comments: 3

Last September I wrote something inspired by the pluck method prototype javascript library, Pluck<T> and posted it on CodeKeep. Basically it creates an array of some type and spins through a collection and picks off the values of the specified property and puts them in an array.  Let's assume we have this class:

public class Customer{
public int Age;
public string Name;
public DateTime Birthday;
Customer(int age, string name, DateTime birthday){
this.Age = age;
this.Name = name;
this.Birthday = birthday;
}
}

And now we create a collection of these guys like this:

List<Customer> customers = new List<Customer>();
customers.Add(new Customer(37, new DateTime(1970, 6, 18), "Chris"));
customers.Add(new Customer(36, new DateTime(1971, 3, 30), "Anja"));
customers.Add(new Customer(3, new DateTime(2004, 4, 11), "Riley"));
customers.Add(new Customer(1, new DateTime(2006, 10, 14), "Emmitt"));

Now I want an array of ages for all of the customers, pre-Pluck you might do something like this:

int[] ages = new int[customers.Count];
for(int i=0;i<customers.Count;i++){
ages[i] = customers[i].Age;
}

...or something similar. What I wanted though was a simple one liner, so I wrote Pluck. Funnily enough, if you didn't look at the CodeKeep sample, here's the first version of Pluck:

public class PluckableList<T> : List<T>{
public Array Pluck(string propertyName){
Type type = typeof(T);
PropertyInfo property = type.GetProperty(propertyName);
Array result = Array.CreateInstance(property.PropertyType, this.Count);
for(int i=0;i<this.Count;i++){
result.SetValue(type.InvokeMember(propertyName, BindingFlags.GetProperty, null, this[i], null), i);
}
return result;
}
}

Well that was nice but I wanted to push this into a static helper class, so without looking at this example(because I thought I remembered the code) I wrote this this morning:

public static T[] Pluck<T, U>(IList<U> items, string propertyName){
T[] result = null;
if (items == null || String.IsNullOrEmpty(propertyName))
return result;

Type type = items[0].GetType();
PropertyInfo property = type.GetProperty(propertyName);
if (!property.CanRead || !typeof(T).IsAssignableFrom(property.PropertyType))
return result;

result = new T[items.Count];
for (int i = 0; i < items.Count; i++){
result[i] = (T)type.InvokeMember(propertyName, BindingFlags.GetProperty, null, items[i], null);
}
return result;
}

The reflective call was bugging me. It wouldn't catch compile time errors. How do I get compile time checking on the pluck method?

Bring in Generic Delegates

I got inspired by the generic Array.Find method that has this signature:

Array.Find(T[] array, Predicate match)

So I came up with my first generic delegate which has this signature:

public delegate TOut Inspector<TOut, TItem>(TItem item);

Next was to create an overload for the Pluck method that would accept that delegate signature as the second parameter. The new method looks like this:

public static TOut[] Pluck<TOut, TItem>(IList<TItem> items, Inspector<TOut, TItem> inspector){
TOut[] result = new TOut[items.Count];
for (int i = 0; i < items.Count; i++){
result[i] = inspector(items[i]);
}
return result;
}

So now if I want the ages of my customers,

int[] ages = ArrayUtils.Pluck<int, Customer>(_customers, delegate(Customer c) { return c.Age; });

VOILA! strongly typed Pluck.  I'm sure something like this already exists somewhere in the framework or is coming as part of 3.x but it was fun writing.

*** UPDATE *** It was pointed out, by Atif, that Array.ConvertAll<TInput,TOutput> will do the trick. This is true so long as you already have an array, otherwise you'll need to create one before using the method. Using Array.ConvertAll with this example and using the fact that List<T> has a ToArray() method, it would look like this:

int[] ages = Array.ConvertAll<Customer, int>(_customers.ToArray(), delegate(Customer c) { return c.Age; });

But while poking around the System.dll using reflector I noticed the Converter generic delegate which is the exact same think as my Inspector delegate, so I switched to using the Converter, the method internals for Pluck did not change at all. So now Pluck looks like this:

public static TOut[] Pluck<TOut, TItem>(IList<TItem> items, Converter<TItem, TOut> converter){
if (items == null || items.Count == 0 || converter == null)
return null;

TOut[] result = new TOut[items.Count];
for (int i = 0; i < items.Count; i++){
result[i] = converter(items[i]);
}
return result;
}

kick it on DotNetKicks.com

Brute Force? I guess I'll just use SubSonic then...

4:49 PM Tuesday Sep 18, 2007 Comments: 5

I'm working on a project now that is a rush job.  Gee, what's new.  Well, there's no project manager(read:anybody who can(should) successfully get us from point A to point B even if that means changing what point B means), and there's not much technical direction.  Luckily, there are about 7 developers, and no technical lead, so basically it's a free for all.  OK, fine. 

"The" Business Object

One developer added "The" business object, a single class containing one class per table in the database schema which is under constant change.   That's fine, unfortunately the "tool" generated 11,000 lines of code.  Again, no biggie.  The problem is that the code doesn't even do one thing, nothin.  They are classes with no more that one property for each field in the table that a class "represents".  That's it.  Funnily enough that didn't immediately pull a *WTF* to me, it was more of a "Huh?". There were no other classes that fill those classes with data or anything, just a bunch of models and that's all folks.

I was thinking that I would try to make some kind of use out of the code by making them all inherit from ActiveRecordBase, put on the right attributes and voila! Useful code.  However the schema is changing rapidly and there's no access to the magic tool that generated the classes in the first place.  So not wanting to be the maintainer of that code(there are almost 100 tables), I went in search of other solutions, determined NOT to write straight sql.

Just Use Brute Force...

I asked another developer working on the project what they were using for interacting with the database.  The response I got obviously spawned this post: "We don't have enough time, I'm just using brute force and writing straight sql and ado.net".

 The Brute Force comment pulled a *WTF* from me.  That's reminiscent of the dot bomb days when you'd write your straight sql by hand for 25 hours a day and spent(read: wasted) most of your time maintaining that stuff and fighting every database change for fear of having to dive into your beautifully hand crafted sql. 

No Thanks...

Enter SubSonic

 I'm a fan of the BuildProvider concept and building the data layer on the fly I learned about when SubSonic was just getting started.  I've rolled a similar approach as a proof of concept using castle's ActiveRecord for the data access.  Anywho, that sure seemed like the approach I wanted.  This was the first post I read by Rob on SubSonic and it's gotten VERY good since then.  Today I watched this screen cast and was sold on picking up the latest version and integrating in our solution.  I was instantly talking to the database without typing one line of sql.  If that's not "brute force" I don't know what is. 

"The Schema Changed and Now I Have to go Fix My Sql"

 Huh.  I reran SubCommander and in approximately 15 seconds, my data layer was regen'd and all changes were now in my code.  Man, I should've used brute force.  Maybe next time...

kick it on DotNetKicks.com

Ctrl + Alt + E

10:23 PM Monday Sep 17, 2007 Comments: 1

Ok here's the code I'm using for this demostration. 

Here's a screencast demonstrating(one way) of breaking on the actual line that caused the exception without setting an explicit breakpoint and/or wrapping a try..catch block that does nothing around the code.  You can inspect any locals while you're on that breakpoint including the exception details.

Test Driven Development...Do You?

7:10 PM Monday Sep 17, 2007 Comments: 0

The Joy of Good Test Driven Development

I came up to a problem on my current project that was tough to think about how to tackle.  Fine, I whipped up a test, went through the usual steps, write a test, see it fail, write enough code to get the test to pass, refactor, repeat.  When I tested for code coverage, I was pleased at my 100%; yep, 100% of the code I just wrote had tests that excercised all lines.  Woo Hoo! The project has grown quite a bit, so I decided to run all of the tests in my solution...

The Pain of Bad Test Driven Development

When I ran all of the tests in my solution, most of them broke.

One reason is that I have a testfixture named "SchemaTests" and it has one test method named "CreateSchema". I'm using ActiveRecord for my persistence layer, and it has a cool method I use, ActiveRecordStarter.CreateSchema, when I'm prototyping something.  Essentially it allows you to write your C# objects first, and figure out how they need to save their stuff second, you end up with a better data model to support your solution, but that's another story in and of itself.(and yes, I ended up recreating the schema and losing anything I had saved to the database) 

Back the problem.

Other tests that broke were ones I had whipped up quickly to excercise(I'm ashamed to admit) external web services :(

BAD DEVELOPER BAD BAD DEVELOPER...

The database tests needed to be somewhere else, once the schema was done on that portion, there really wasn't a need to run any of the tests, it's just saving stuff and that's what ActiveRecord does for you.  The dependency on  external services in my tests was me being lazy(and that's lazy in the bad way).

Now What

I yanked every test that interacted with an external resource. Sadly, that also removed a ton of coverage. I had gone down the path of fixing the tests that broke, but upon looking at what they did, I realized they weren't very good to begin with, most likely not written with Test Driven Development in mind. My report card is not looking good on this so far.

Luckily, the code is pretty well factored, so I'm able to mock all of the external services with RhinoMocks.  I have some more tests to write (which always sucks after the fact) but that's my punishment.

kick it on DotNetKicks.com

CopyTo(T target) ... Brilliant? or Brilliantly Shitty?

3:42 PM Sunday Sep 16, 2007 Comments: 5
public virtual void CopyTo(T target)
{
    Type sourceType = this.GetType();
    Type destType = typeof(T);
    foreach (PropertyInfo sourceProp in sourceType.GetProperties())
    {
        PropertyInfo destProp = destType.GetProperty(sourceProp.Name);
        if (sourceProp.PropertyType.IsByRef
        	|| destProp == null
        	|| !destProp.PropertyType.IsAssignableFrom(sourceProp.PropertyType))
        	continue;

        object val = sourceType.InvokeMember(sourceProp.Name, BindingFlags.GetProperty, null, this, null);
        destType.InvokeMember(sourceProp.Name, BindingFlags.SetProperty, null, target, new object[] { val });
    }
}

Basically I needed a way to copy all commonly named properties from an instance of one thing, to instance of another thing, without typing the the properties out. Performance is not a huge deal(for now), hence the use of reflection. Here's example usage. Does something like this exist already exist in the framework?

kick it on DotNetKicks.com

tafiti...very cool

12:48 PM Sunday Sep 16, 2007 Comments: 0

found this via Peter Himschoot's blog. cool sample app using silverlight: http://www.tafiti.com/

Setting up ILDASM

12:19 PM Saturday Sep 15, 2007 Comments: 0

Here's a little screencast on how to set up ILDASM to use from within visual studio. 

Try..Catch...Now What

2:8 PM Friday Sep 14, 2007 Comments: 14

Grrrrr.  This is a little bit of a rant.  I don't get it.  I'm working on a project right now that has code like this:

public SqlConnection GetYourFavoriteConnection()
{
  SqlConnection Conn;
  try
  {
    Conn = new SqlConnection(connString);
    Conn.Open();
  }
  catch (Exception e)
  {
    throw new Exception(e.Message, e);
  }
  return Conn;
}

Just to be clear, I'm focusing on the use of the try...catch block only.  The project I'm working on is riddled with this shit code.  Why is it shit code? Well, what was wrong with the original exception? Not good enough for your code?? Not as cool as a "new" Exception?? Am I missing something?

My Beef

Where's the value add? What's the point of catching an exception if you're not going to do anything with it?  Here's another good one,

SqlConnection Conn;
try
{
  //do stuff with Conn
}
catch(Exception e)
{
  throw new Exception(e.Message, e);
}
finally
{
  if (Conn != null)
  {
    Conn.Close();
  }
}

I've blogged about this before and apparently I'm blogging about it now. The using statement will do heavy lifting for you.  The above could be rewritten like this:

using (SqlConnection Conn = new SqlConnection("connection string"))
{
  //do stuff with Conn here
}

What's So Special About 'Using'??

The following code:

using System;
using System.Data.SqlClient;
namespace ConsoleApplication1
{
  public class Program
  {
    public static void Main(string[] args)
    {
      using (SqlConnection cn = new SqlConnection("connection string"))
      {         
      }
    }
  }
}

...produces this IL

.method public hidebysig static void  Main(string[] args) cil managed
{
  .entrypoint
  // Code size       34 (0x22)
  .maxstack  2
  .locals init ([0] class [System.Data]System.Data.SqlClient.SqlConnection cn,
           [1] bool CS$4$0000)
  IL_0000:  nop
  IL_0001:  ldstr      "connection string"
  IL_0006:  newobj     instance void [System.Data]System.Data.SqlClient.SqlConnection::.ctor(string)
  IL_000b:  stloc.0
  .try
  {
    IL_000c:  nop
    IL_000d:  nop
    IL_000e:  leave.s    IL_0020
  }  // end .try
  finally
  {
    IL_0010:  ldloc.0
    IL_0011:  ldnull
    IL_0012:  ceq
    IL_0014:  stloc.1
    IL_0015:  ldloc.1
    IL_0016:  brtrue.s   IL_001f
    IL_0018:  ldloc.0
    IL_0019:  callvirt   instance void [mscorlib]System.IDisposable::Dispose()
    IL_001e:  nop
    IL_001f:  endfinally
  }  // end handler
  IL_0020:  nop
  IL_0021:  ret
} // end of method Program::Main

Notice anything?? Like the try..finally?? Ya, the using statement will put those in for you.

It Calls Dispose For You, So What?

Well for one that means less code to write.  Read here for the other.  For those who do not trust the documentation here's the code for Dispose as seen through Reflector:

protected override void Dispose(bool disposing)
{
    if (disposing)
    {
        this._userConnectionOptions = null;
        this._poolGroup = null;
        this.Close();
    }
    this.DisposeMe(disposing);
    base.Dispose(disposing);
}

Take note of the fact that it calls Close for you. No need to code for it...

kick it on DotNetKicks.com

Array.ConvertAll ... Even Better!

9:36 PM Tuesday Sep 11, 2007 Comments: 0

Previously I mentioned how slick Array.ConvertAll was, but check this out, it's even better, I totally missed this first time around, alternatively you can do this:

string[] stringarray = new string[]{ "1", "2", "3" };
int[] intarray = Array.ConvertAll<string, int>(stringarray, Convert.ToInt32);

Wicked Cool!