views:

806

answers:

1

Extension Methods for Indexers, would they be good ?

I was playing around with some code that re-hydrates POCO's.

The code iterates around rows returned from a SqlDataReader and and uses reflection to assign properties from column values. Down my call stack I had a code a line like this :-

poco.Set(“Surname”, “Smith”); // uses extension method ...

The Set method was written as an extension method.

It would be great to have been able to write code like this

poco[“Surname”] = “Smith”;  // extension methods for indexers ?

ie I wanted to write an extension method for indexer

Are there good reason why .Net does not have extension methods for indexers? Do other people have other good uses for extension method indexers ?

as an aside ... If we could write extension methods for indexers then we could write code like this …

var poco = PocoFactory();  
    poco.Surname = “Smith”; // is this JavaScript ...
    poco[Surname] = “Smith” ; // … or is this c# or both

Some snippets from my code

/////////////////////////////////////////////
// Client calling code
IDab dab = DabFactory.Create( "Northwind" );
string sql = @"select * from Customers ";
var persons = dab.ExecuteReader<NorthwindCustomer>(sql);
if (dab != null{
   Assert.That(persons[0].CustomerID , Is.EqualTo("ALFKI"));}
/////////////////////////////////////////////
List<T> IDab.ExecuteReader<T>(string commandText) 
{
    List<T> pocos = new List<T>();
    // setup connection
    SqlDataReader reader = command.ExecuteReader(CommandBehavior.CloseConnection);
    while (reader.Read())
    {
            Dictionary<string, int> colMappings = null ;
            if (colMappings == null){
                colMappings = reader.GetSqlDataReaderColumnMappings();}
            T poco = new T();
            poco.DbToMem<T>(reader, colMappings);
            pocos.Add(poco);
        }
    }
    // connection cleanup ...
    return pocos ;
}

// the set extension method signature
public static void Set<T>(this T thisClientObject, string thisPropertyName, object newValue) where T : class
+1  A: 

Indexers share a lot of commonality with properties (under the hood, an indexer is a property with an index), and extension properties don't exist. Agreed, there would be scenarios where they are handy.

Re the scenario presented - in some ways, this is quite like dynamic. Of course, if you declare an interface that has a string indexer, then your reader-code could use it directly - but it would be a lot of unnecessary work to implement this interface repeatedly!

Re the extension method; does this use regular reflection? You might want to look at tricks like HyperDescriptor, which might save a lot of CPU time if you are doing lots of this. Typical usage would then be:

PropertyDescriptorCollection props = TypeDescriptor.GetProperties(typeof(T));
while (reader.Read())
{
     T poco = new T();
     // abbreviated...
     (per prop)
        props[propName].SetValue(poco, cellValue);
}

You can optimise this further by looking at the returned columns first (once per grid, not per row), and only accessing matched columns...

Or alternatively, look at ORM tools; Expression can also be used to do data reading (I have a complete example of this somewhere on usenet, for DbLinq)

Marc Gravell
interesting thanks, I will have a look.
judek