Question about indexers and / or generics

how can I find out if an object implements an indexer ?, I need to separate the logic for DataRow and IDataReader, but they have no interface.

I also tried with generics, but I don’t know what restriction should be placed in the where clause.

public class Indexer { // myObject should be a DataRow or a IDataReader private object myObject; public object MyObject { get { return myObject; } set { myObject = value; } } // won't compile, myObject has no indexer public object this[int index] { get { return myObject[index]; } set { myObject[index] = value; } } public Indexer(object myObject) { this.myObject = myObject; } } public class Caller { void Call() { DataRow row = null; IDataReader reader = null; var ind1 = new Indexer(row); var ind2 = new Indexer(reader); var val1 = ind1[0]; var val2 = ind1[0]; } } 
+3
generics c #
Mar 26 '09 at 22:30
source share
3 answers

You will need to declare an interface with the indexer property, use this interface as a constraint, and a class of type arguments will need to implement this interface to satisfy the constraint.

Since you do not control the classes you want to use, this will not work.

An alternative is to use the Indexer class for get / set operations as separate parameters:

 public class Indexer { private Func<int, object> getter; private Action<int, object> setter; public object this[int index] { get { return getter(index); } set { setter(index, value); } } public Indexer(Func<int, object> g, Action<int, object> s) { getter = g; setter = s; } } public static class IndexerExtensions { public static Indexer ToIndexer(this DataRow row) { return new Indexer(n => row[n], (n, v) => row[n] = v); } public static Indexer ToIndexer(this IDataReader row) { return new Indexer(n => row[n], (n, v) => row[n] = v); } } 

Then you can do the following:

 DataRow row = null; IDataReader reader = null; var ind1 = row.ToIndexer(); var ind2 = reader.ToIndexer(); var val1 = ind1[0]; var val2 = ind1[0]; 
+5
Mar 26 '09 at 22:34
source share

You can make your Indexer an abstract base class with two subclasses, one for DataRow and one for IDataReader.

To make it easier to use, factory methods could exist, for example:

 var ind1 = Indexer.CreateFromDataRow(row); var ind2 = Indexer.CreateFromIDataReader(reader); 

They can create a specific base class for this type, with its own logic for handling indexing.

This avoids the overhead of type checking constantly for each call to get / set (due to one virtual property instead of the standard property).

+3
Mar 26 '09 at 10:40
source share
 get { DataRow row = myObject as DataRow; if (row != null) return row[index]; IDataReader reader = myObject as IDataReader; if (reader != null) return reader[index]; } 

and use the same logic to set {}

+1
Mar 26 '09 at 22:38
source share



All Articles