Укажите тип генериков, используя поле - PullRequest
1 голос
/ 13 марта 2012

Предположим, у меня есть следующий класс:

public class MyClass
{
    public decimal myDecimal;
    public string myString;
}

Я хочу использовать метод DataRowExtensions Поле <>

В настоящее время я использую класс следующим образом:

MyClass myClass = new MyClass();
myClass.myDecimal = row.Field<decimal>("MyDecimalColumnName");
myClass.myString = row.Field<string>("MyStringColumnName");

Однако, если я когда-нибудь решу изменить тип myDecimal на что-то отличное от decimal, я хочу, чтобы вызов row.Field отражал правильные данные.

Я хочу что-то похожее на следующий синтаксис:

myClass.myDecimal = row.Field<typeof(myClass.myDecimal)>("MyDecimalColumnName");

Это не компилируется, и я понятия не имею, как использовать typeof или GetType(), чтобы просто вернуть decimal, что бы это ни былозвонил.

Есть ли способ сделать это, или что-то подобное?Я полагал, что это может быть выполнено во время компиляции, так как типы уже известны, и поскольку универсальные шаблоны являются конструкциями времени компиляции.

Спасибо!

Ответы [ 2 ]

5 голосов
/ 13 марта 2012

Во-первых, обратите внимание, что публичные поля обычно очень плохая идея; но если мы предположим, что это было частное вспомогательное поле, здесь есть 2 интересных варианта;

Во-первых, использовать вывод общего типа; это не работает для типа return , но работает для параметров, поэтому вы можете получить:

row.GetField("MyDecimalColumnName", out obj.someField);

где это:

GetField<T>(string name, out T value);

Другим приемом было бы использование неявных операторов, то есть GetField(string) возвращает фиктивный объект, имеющий неявные операторы преобразования, для нескольких типов, таких как int, decimal и т. Д., И выполняет работу / преобразование в оператор. Немного хакерский, но сработает - синтаксис будет:

myClass.myDecimal = row.Field("SomeColumn")

с:

SomeDummyType GetField(string name);

и SomeDummyType с оператором неявного статического преобразования или несколькими.

Тем не менее! IMO лучший вариант здесь - использовать инструмент, такой как ORM или микро-ORM, чтобы загрузить значения для вас, и вообще не использовать DataRow.

Еще один простой вариант - перейти на старую школу:

myClass.myDecimal = (decimal)row["SomeColumn"];

Я имею в виду - действительно ли .Field<T> вам так сильно помогает? Вы действительно реорганизуете свои занятия достаточно часто, чтобы об этом стоило беспокоиться?

1 голос
/ 13 марта 2012

Вы можете использовать рефлексию для динамического построения правильного универсального метода:

MyClass myClass = new MyClass();
var myType = typeof(MyClass.myDecimal);
var myMethod = Type.GetType("System.Data.DataRowExtensions")
   .GetMethod("Field", new[]{typeof(DataRow), typeof(string));
var genericMethod = myMethod.MakeGenericMethod(new[]{myType});

myClass.myDecimal = genericMethod.Invoke(row, new object[]{"MyDecimalColumnName"});
...