Подойдут ли методы расширения для индексаторов?
Подойдут ли методы расширения для индексаторов?
Я играл с некоторым кодом, который повторно гидратирует POCO.
Код выполняет итерацию по строкам, возвращаемым из SqlDataReader, и использует отражение для назначения свойств из значений столбцов. В моем стеке вызовов у меня был код такой строки: -
poco.Set("Surname", "Smith"); // uses extension method ...
Метод Set был написан как метод расширения.
Было бы здорово написать такой код
poco["Surname"] = "Smith"; // extension methods for indexers ?
т.е. я хотел написать метод расширения для индексатора
Есть ли веская причина, по которой .Net не имеет методов расширения для индексаторов? Есть ли у других хорошее применение индексаторам методов расширения?
в стороне ... Если бы мы могли писать методы расширения для индексаторов, мы могли бы написать такой код ...
var poco = PocoFactory();
poco.Surname = “Smith”; // is this JavaScript ...
poco[Surname] = “Smith” ; // … or is this c# or both
Некоторые фрагменты моего кода
/////////////////////////////////////////////
// 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
Ответов (2)2
Индексаторы имеют много общего со свойствами (под капотом индексатор - это свойство с индексом), а свойства расширения не существуют. Договорились, будут сценарии, где они пригодятся.
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)