我正在从源中选择一些数据,并且希望将其传递给处理数据的通用方法。我选择的每个属性都需要一些关联的元数据来进行处理。这大致就是我希望能够做到的:
var items = from i in db.bar
select new {
a = i.Prop1.ToString(),
b = i.Prop2.ToString(),
c = Prop3
};
// Roughly what I would like to be able to do:
ProcessData(items,
new DataSelector() { Header = "head1", Selector = (d => d.Prop1) },
new DataSelector() { Header = "head2", Selector = (d => d.Prop2) });
我能得到的最接近的是:
private class DataSelector<T> {
public string Header { get; set; }
public Func<T, string> Selector { get; set; }
}
private static void Process<T>(IEnumerable<T> stuff,
params ColumnDef<T>[] defs) {
foreach (var item in stuff) {
// Use all defs like...
Console.WriteLine(defs[0].Header + ": " + defs[0].Selector(item));
}
}
Process(items,
new DataSelector<dynamic>() { Header = "head1", Selector = (d => d.Prop1) });
但这允许我写(d => d.NonExistantProp)
它会编译并在运行时失败(嘘声)。我还可以对单个属性执行此操作并维护类型安全,因为该类型似乎是隐式计算出来的,但这不会让我传递参数集:
private static void Process<T>(IEnumerable<T> stuff,
string header,
Func<T, string> selector) {
// stuff happens
}
Process(items, "head1", (d => d.Prop1));
那么...有没有办法维护选择器以及相关数据组的编译时类型安全?
脚注:我很感激我可以拥有 Process<T>(IEnumerable<T> items, List<string> headers, params Func<T, string> selectors[])
但如果 header 未与选择器配对,也会产生运行时错误。
最佳答案
您需要的是创建一个 DataSelector
的方法,该方法使用基于给定序列(或项目,或使用该类型的任何其他内容)的类型推断。
我们可以创建一个非通用的 DataSelector 对应项,它可以有一个静态 Create
方法,该方法可以以允许类型推断的方式编写:
private class DataSelector
{
public static DataSelector<T> Create<T>(IEnumerable<T> sequence,
string header, Func<T, string> selector)
{
return new DataSelector<T>() { Header = header, Selector = selector };
}
}
现在调用者可以写:
Process(items, DataSelector.Create(items, "first", item => item.Prop1));
我们现在正在推断数据选择器的 T
类型,并且不需要指定没有名称的类型。
请注意,我们实际上并没有在此 Create
方法中迭代序列;它根本没有被使用;它基本上是一个虚拟参数。
我们看到这种模式在 .NET 框架的许多地方都有使用,例如 Tuple
。
关于c# - 我可以使用 linq 结果中的匿名类型来创建类集合作为方法参数的一部分吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20078491/