草庐IT

c# - MemberBinding LINQ 表达式有哪些示例?

coder 2024-05-24 原文

有三种可能,但我找不到例子:

  1. System.Linq.Expressions.MemberAssignment
  2. System.Linq.Expressions.MemberListBinding
  3. System.Linq.Expressions.MemberMemberBinding

我想写一些单元测试,看看我能不能处理它们,但我不知道怎么写,除了第一个,它似乎是 new Foo { Property = "value"} 其中 Property = "value"MemberAssignment 类型的表达式。

另见 MSDN article .

最佳答案

我在这些示例中使用的类如下:

public class Node
{
  //initialise non-null, so we can use the MemberMemberBinding
  private NodeData _data = new NodeData();
  public NodeData Data { get { return _data; } set { _data = value; } }
  //initialise with one element so you can see how a MemberListBind
  //actually adds elements to those in a list, not creating it new.
  //Note - can't set the element to 'new Node()' as we get a Stack Overflow!
  private IList<Node> _children = new List<Node>() { null };
  public IList<Node> Children 
    { get { return _children; } set { _children = value; } }
}

public class NodeData
{
  private static int _counter = 0;
  //allows us to count the number of instances being created.
  public readonly int ID = ++_counter;
  public string Name { get; set; }
}

首先,您可以让 C# 编译器生成表达式,以便您通过执行以下操作来研究它们的工作原理:

Expression<Func<Node>> = () => new Node();

将生成一个内联表达式,其中包含对 Expression.New 的调用,传递 Node 类型的 ConstructorInfo。在 Reflector 中打开输出 DLL,看看我的意思。

我应该首先提到,您询问的这三种表达式类型通常在 Expression.New 中的 MemberBinding[] 数组中传递,或者相互嵌入(因为成员初始值设定项本质上是递归的)。

关于情节......

成员分配

MemberAssignment 表达式表示具有给定表达式返回值的新实例的单个成员的设置。它是使用 Expression.Bind 工厂方法在代码中生成的。这是您将看到的最常见的情况,在 C# 代码中,这等同于以下内容:

new NodeData() { /* start */ Name = "hello" /* end */ };

new Node() { /* start */ Data = new NodeData() /* end */ };

成员成员绑定(bind)

MemberMemberBinding 表示已经初始化的成员的成员的内联初始化(即新成员,或者无论如何都不能为 null 的结构)。它是通过 Expression.MemberBind 创建的,不代表创建新实例。因此,它与 MemberBind 方法的不同之处在于,它不采用 ConstructorInfo,而是采用对 Property Get 方法(属性访问器)的引用。因此,尝试以这种方式初始化从 null 开始的成员将导致 NullReferenceException。

因此,要在代码中生成它,您可以这样做:

new Node() { /* start */ Data = { Name = "hello world" } /* end */};

这可能看起来有点奇怪,但这里发生的是正在执行 Data 的属性 get 方法以获取对已初始化成员的引用。有了它,内部的 MemberBindings 就会依次执行,所以上面的代码实际上并没有覆盖数据,而是这样做:

new Node().Data.Name = "hello world";

这就是为什么需要这种表达式类型的原因,因为如果你必须设置多个属性值,你不能在一行中完成它,除非有一些特殊的表达式/语法来完成它。如果 NodeData 有另一个字符串成员 (OtherName),您也想同时设置它,没有初始化语法/表达式,您必须这样做:

var node = new Node();
node.Data.Name = "first";
node.Data.OtherName = "second";

这不是一个类轮 - 但这是:

var node = new Node() { Data = { Name = "first", OtherName="second" } };

Data = 位是 MemberMemberBinding。

我希望这很清楚!

成员列表绑定(bind)

Expression.ListBind 方法创建(还需要调用 Expression.ElementInit),这类似于 MemberMemberBinding(对象的成员是 不是被重新创建),但这一次,它是一个 ICollection/IList 的实例,它被添加到 带有内联元素.:

new Node() { /* start */ Children = { new Node(), new Node() } /* end */ };

因此,最后两个表达式有点边缘情况,但肯定是您很可能会遇到的事情,因为它们显然非常有用。

最后,我附上了一个您可以运行的单元测试,它将证明我对这些表达式所做的断言 - 如果您反射(reflect)方法主体,您会看到相关的工厂方法在我强调的点被调用带有评论 block :

[TestMethod]
public void TestMethod1()
{
  Expression<Func<Node>> e = 
    () => new Node() { Data = new NodeData() };

  Expression<Func<Node>> e2 = 
    () => new Node() { Data = { Name = "MemberMemberBinding" } };

  Expression<Func<Node>> e3 = 
    () => new Node() { Children = { new Node(), new Node() } };

  var f = e.Compile();
  var f2 = e2.Compile();
  var f3 = e3.Compile();

  var node = f();
  //proves that this data was created anew as part of the expression.
  Assert.AreEqual(2, node.Data.ID);
  var node2 = f2();
  //proves that the data node's name was merely initialised, and that the
  //node data itself was not created anew within the expression.
  Assert.AreEqual(3, node2.Data.ID);
  Assert.AreEqual("MemberMemberBinding", node2.Data.Name);
  var node3 = f3();
  //count is three because the two elements in the MemberListBinding
  //merely added two to the existing first null item.
  Assert.AreEqual(3, node3.Children.Count);
}

好了,我认为应该涵盖它。

您是否应该在您的代码中支持它们是另一回事! ;)

关于c# - MemberBinding LINQ 表达式有哪些示例?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2917448/

有关c# - MemberBinding LINQ 表达式有哪些示例?的更多相关文章

  1. ruby 正则表达式 - 如何替换字符串中匹配项的第 n 个实例 - 2

    在我的应用程序中,我需要能够找到所有数字子字符串,然后扫描每个子字符串,找到第一个匹配范围(例如5到15之间)的子字符串,并将该实例替换为另一个字符串“X”。我的测试字符串s="1foo100bar10gee1"我的初始模式是1个或多个数字的任何字符串,例如,re=Regexp.new(/\d+/)matches=s.scan(re)给出["1","100","10","1"]如果我想用“X”替换第N个匹配项,并且只替换第N个匹配项,我该怎么做?例如,如果我想替换第三个匹配项“10”(匹配项[2]),我不能只说s[matches[2]]="X"因为它做了两次替换“1fooX0barXg

  2. c# - 如何在 ruby​​ 中调用 C# dll? - 2

    如何在ruby​​中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL

  3. C# 到 Ruby sha1 base64 编码 - 2

    我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha

  4. 基于C#实现简易绘图工具【100010177】 - 2

    C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.

  5. postman——集合——执行集合——测试脚本——pm对象简单示例02 - 2

    //1.验证返回状态码是否是200pm.test("Statuscodeis200",function(){pm.response.to.have.status(200);});//2.验证返回body内是否含有某个值pm.test("Bodymatchesstring",function(){pm.expect(pm.response.text()).to.include("string_you_want_to_search");});//3.验证某个返回值是否是100pm.test("Yourtestname",function(){varjsonData=pm.response.json

  6. ruby - 正则表达式将非英文字母匹配为非单词字符 - 2

    @raw_array[i]=~/[\W]/非常简单的正则表达式。当我用一些非拉丁字母(具体来说是俄语)尝试时,条件是错误的。我能用它做什么? 最佳答案 @raw_array[i]=~/[\p{L}]/使用西里尔字符进行测试。引用:http://www.regular-expressions.info/unicode.html#prop 关于ruby-正则表达式将非英文字母匹配为非单词字符,我们在StackOverflow上找到一个类似的问题: https://

  7. ruby - 正则表达式在哪个位置失败? - 2

    我需要一个非常简单的字符串验证器来显示第一个符号与所需格式不对应的位置。我想使用正则表达式,但在这种情况下,我必须找到与表达式相对应的字符串停止的位置,但我找不到可以做到这一点的方法。(这一定是一种相当简单的方法……也许没有?)例如,如果我有正则表达式:/^Q+E+R+$/带字符串:"QQQQEEE2ER"期望的结果应该是7 最佳答案 一个想法:你可以做的是标记你的模式并用可选的嵌套捕获组编写它:^(Q+(E+(R+($)?)?)?)?然后你只需要计算你获得的捕获组的数量就可以知道正则表达式引擎在模式中停止的位置,你可以确定匹配结束

  8. ruby-on-rails - 您希望看到哪些 Rails 插件? - 2

    您认为可以作为插件很好地存在于您的Rails应用程序中必须实现的哪些行为?您过去曾搜索过哪些插件功能但找不到?哪些现有的Rails插件可以改进或扩展,如何改进或扩展? 最佳答案 我希望在管理界面中看到一个引擎插件,它提供了应用程序中所有模型的仪表板摘要,以及可配置的事件图表。 关于ruby-on-rails-您希望看到哪些Rails插件?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questio

  9. ruby - 有没有办法从 ruby​​ case 语句中访问表达式? - 2

    我想从then子句中访问c​​ase语句表达式,即food="cheese"casefoodwhen"dip"then"carrotsticks"when"cheese"then"#{expr}crackers"else"mayo"end在这种情况下,expr是食物的当前值(value)。在这种情况下,我知道,我可以简单地访问变量food,但是在某些情况下,该值可能无法再访问(array.shift等)。除了将expr移出到局部变量然后访问它之外,是否有直接访问caseexpr值的方法?罗亚附注我知道这个具体示例很简单,只是一个示例场景。 最佳答案

  10. ruby - 正则表达式 - 排除一个字符 - 2

    这是一个例子:s="abcd+subtext@example.com"s.match(/+[^@]*/)Result=>"+subtext"问题是,我不想在其中包含“+”。我希望结果是“潜台词”,没有+ 最佳答案 您可以在正则表达式中使用括号来创建匹配组:s="abcd+subtext@example.com"s=~/\+([^@]*)/&&$1=>"subtext" 关于ruby-正则表达式-排除一个字符,我们在StackOverflow上找到一个类似的问题:

随机推荐