如何知道对象是否实现索引器?我需要共享DataRow和IDataReader的逻辑,但它们不共享任何接口。
我也尝试过泛型,但不知道我应该对where子句施加什么限制。
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];
}
}
答案 0 :(得分:5)
您需要声明具有索引器属性的接口,使用该接口作为约束,并且类型参数类需要实现该接口以满足约束。
由于您无法控制要使用的类,因此无效。
另一种方法是让Indexer
类将get / set操作作为单独的参数:
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);
}
}
然后你可以这样做:
DataRow row = null;
IDataReader reader = null;
var ind1 = row.ToIndexer();
var ind2 = reader.ToIndexer();
var val1 = ind1[0];
var val2 = ind1[0];
答案 1 :(得分:3)
你可以使你的Indexer成为一个抽象基类,有两个子类,一个用于DataRow,另一个用于IDataReader。
为了便于使用,可能存在2种工厂方法,例如:
var ind1 = Indexer.CreateFromDataRow(row);
var ind2 = Indexer.CreateFromIDataReader(reader);
他们可以为该类型创建一个特定的基类,它有自己的逻辑来处理索引。
这避免了每次get / set调用不断检查类型的开销(以单个虚拟属性而不是标准属性为代价)。
答案 2 :(得分:1)
get {
DataRow row = myObject as DataRow;
if (row != null)
return row[index];
IDataReader reader = myObject as IDataReader;
if (reader != null)
return reader[index];
}
并对set {}
使用相同的逻辑