【问题标题】:Generic method that accepts generic list of Expression<Func>接受 Expression<Func> 的通用列表的通用方法
【发布时间】:2018-08-22 06:57:38
【问题描述】:

我已经声明了多个这些变量,但是我怎样才能将它们放入一个通用列表中?

Expression<Func<poco, string>> fieldToUpdate1 = x => x.Name;
Expression<Func<poco, bool>> fieldToUpdate2 = x => x.Id;

目前我只能为通用列表指定一种类型。

所以我可以得到List&lt;string&gt;List&lt;bool&gt;。但不是两者兼而有之。我希望能够有一个接受两者的通用列表,以便我可以将该列表作为参数传递。

用例: 我正在尝试做的用例是为 Mongo 方法 updateOne 创建一个通用包装器。带有以下签名。我想创建一个接受两个参数的通用包装器。我可以使用这些参数来调用实际的 mongo 实现。像这样的:

GenericWrapper(Expression<Func<TDocument, bool>> filter, List<(Expression<Func<TDocument, TField>> expression, TField actual value)>)

问题是 TField 只能是一种类型。所以我只能这样做:

Expression<Func<Student, string>> fieldToUpdate1 = x => x.name;
Expression<Func<Student, int>> fieldToUpdate2 = x => x.testScore;
var expressions = new List<(Expression<Func<Student, int>>    expression, int value)>();
var item1 = (expression: fieldToUpdate2, value: 4);
var item2 = (expression: fieldToUpdate1, value: "test");
expressions.Add(item1);
//I can't add item2 since its of a different type. I can only  pass a list of the same type. And my generic wrapper function will only accept a list of one type

http://api.mongodb.com/csharp/current/html/M_MongoDB_Driver_IMongoCollectionExtensions_UpdateOne__1.htm

public static UpdateResult UpdateOne<TDocument>(
this IMongoCollection<TDocument> collection,
Expression<Func<TDocument, bool>> filter,
UpdateDefinition<TDocument> update,
UpdateOptions options = null,
CancellationToken cancellationToken = null

)

关于如何制作这个通用包装器的任何想法?

【问题讨论】:

  • 您可以将object 指定为列表类型,然后在从列表中读取时进行转换。
  • 还可以退后一步问自己:“为什么我需要这么奇怪的东西?”。也许你会得到一个更合理的设计。
  • 您将不得不定位键。 Key1Key2 当您想要传递特定参数时。您可以遍历想要传入的 w/e,然后在将其添加到密钥之前检查类型。
  • "但是我怎样才能把它们放到一个通用列表中呢?"你到底想把什么放在一个列表中? fieldToUpdate1fieldToUpdate2 ?还是要将Func 的返回值放入列表中?抱歉(对我的大脑来说可能为时过早)但我很困惑,这个问题我不清楚
  • 这听起来也有点像 XY 问题。您可以发布一个使用fieldToUpdate1 的用例吗?

标签: c# generics generic-programming generic-list


【解决方案1】:

由于Expression&lt;T&gt; 继承自Expression,您可以将其放入List&lt;Expression&gt;

List<Expression> expressions = new List<Expression>();
expressions.Add(fieldToUpdate1);
expressions.Add(fieldToUpdate2);

【讨论】:

  • 由于他的表达式是 Expression> 类型,他可以使用 LambdaExpression 而不是 Expression 来确保至少只提供 lambda 表达式作为参数。
【解决方案2】:

你可以使用object作为返回值:

Expression<Func<poco, object>> fieldToUpdate1 = x => x.Name;
Expression<Func<poco, object>> fieldToUpdate2 = x => x.Id;
List<Expression<Func<poco, object>>> testList = new List<Expression<Func<poco, object>>>();
testList.Add(fieldToUpdate1);
testList.Add(fieldToUpdate2);

总之,总体的设计看起来有点奇怪,因为到最后,你至少得投出结果。

【讨论】:

  • Matthias 的答案同样有效,甚至不需要你的 poco 对象。
猜你喜欢
  • 1970-01-01
  • 2016-01-12
  • 1970-01-01
  • 1970-01-01
  • 2016-11-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多