Как уменьшить количество объявлений типов при использовании лямбда-параметров?
-
09-09-2019 - |
Вопрос
Ниже приведена сильно урезанная версия некоторого кода, который у меня есть
public class DataInfo<T>
{
public DataInfo(string description, Func<T, object> funcToGetValue)
{
this.description = description;
this.funcToGetValue= funcToGetValue;
}
public readonly string description;
public readonly Func<T, object> funcToGetValue;
}
public class DataType1
{
public int fieldA { get; set; }
public string fieldB { get; set; }
}
public class CurrentUse
{
static List<DataInfo<DataType1>> data1 = new List<DataInfo<DataType1>>()
{
new DataInfo<DataType1>("someStuff", data => data.fieldA),
new DataInfo<DataType1>("someOtherStuff", data => data.fieldB)
};
}
(Существует много типов, и не волнуйтесь, на самом деле не все являются общедоступными!)
Это работает, и все в порядке, насколько это возможно, но тот факт, что я должен продолжать повторять new DataInfo<DataType1>
меня это немного беспокоит.
Я попытался создать не общую вспомогательную версию DataInfo для создания объектов для меня следующим образом
public class DataInfo
{
public static DataInfo<T> Create<T>(string description, Func<T, object> func)
{
return new DataInfo<T>(description, func);
}
}
public class DesiredUse
{
static List<DataInfo<DataType1>> data1 = new List<DataInfo<DataType1>>()
{
DataInfo.Create("someStuff", data => data.fieldA),
DataInfo.Create("someOtherStuff", data => data.fieldB)
};
}
Но это не работает, поскольку компилятор не может разрешить FieldA & FieldB, поскольку он не может определить тип данных.
Есть какие-нибудь идеи, как я могу избавиться от дублированной информации о типе?Я не возражаю вносить изменения, при условии, что в итоге у меня будет список источников данных
Решение
Я бы создал класс builder:
public sealed class DataInfoListBuilder<T> : IEnumerable
{
private readonly List<DataInfo<T>> list = new List<DataInfo<T>>();
public void Add(string description, Func<T, object> function)
{
list.Add(DataInfo.Create<T>(description, function));
}
public List<DataInfo<T>> Build()
{
return list;
}
public IEnumerator GetEnumerator()
{
throw new InvalidOperationException
("IEnumerator only implemented for the benefit of the C# compiler");
}
}
Затем используйте его как:
static List<DataInfo<DataType1>> data1 = new DataInfoListBuilder<DataType1>
{
{ "someStuff", data => data.fieldA },
{ "someOtherStuff", data => data.fieldB }
}.Build();
Я не тестировал это, но я думаю, что это должно сработать.Вы могли бы сделать его универсальным типом в DataInfo, и в этом случае вы бы использовали:
static List<DataInfo<DataType1>> data1 = new DataInfo<DataType1>.Builder
{ ... }.Build();
Другие советы
Возможно, вы можете наследовать от List> и предоставить специализированный метод добавления:
public class SpecialList<T> : List<DataInfo<T>>
{
public void Add(string description, Func<T, object> func)
{
base.Add(new DataInfo<T>(description, func));
}
}
Затем вы можете использовать его следующим образом:
public class CurrentUse
{
public static SpecialList<DataType1> Data1
{
get
{
SpecialList<DataType1> list = new SpecialList<DataType1>();
list.Add("someStuff", data => data.fieldA);
list.Add("someOtherStuff", data => data.fieldB);
return list;
}
}