{"id":472,"date":"2010-02-09T18:00:50","date_gmt":"2010-02-09T16:00:50","guid":{"rendered":"http:\/\/www.limilabs.com\/blog\/?p=472"},"modified":"2010-02-09T18:00:50","modified_gmt":"2010-02-09T16:00:50","slug":"property-name-from-lambda","status":"publish","type":"post","link":"https:\/\/www.limilabs.com\/blog\/property-name-from-lambda","title":{"rendered":"How to get property name from lambda"},"content":{"rendered":"<p>The whole idea is simple, we want this test to pass:<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n&#x5B;Test]\nvoid CanGetPropertyName_UsingLambda()\n{\n  Assert.AreEqual(&quot;Name&quot;, PropertyName.For&lt;person&gt;(x =&gt; x.Name));\n}\n<\/pre>\n<p>It seams nice and convenient way of getting property name.<br \/>\nWhole test fixture looks as follows:<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n&#x5B;TestFixture]\npublic class PropertyNameTests\n{\n    public string NameForTest { get; set; }\n\n    &#x5B;Test]\n    public void CanGetPropertyName_SameType_UsingLambda()\n    {\n        Assert.AreEqual(&quot;NameForTest&quot;,\n            PropertyName.For(() =&gt; NameForTest));\n    }\n\n    &#x5B;Test]\n    public void CanGetPropertyName_UsingLambda()\n    {\n        Assert.AreEqual(&quot;Name&quot;,\n            PropertyName.For&lt;person&gt;(x =&gt; x.Name));\n        Assert.AreEqual(&quot;Age&quot;,\n            PropertyName.For&lt;person&gt;(x =&gt; x.Age));\n    }\n\n    &#x5B;Test]\n    public void CanGetPropertyName_Composite_UsingLambda()\n    {\n        Assert.AreEqual(&quot;Home.City&quot;,\n            PropertyName.For&lt;person&gt;(x =&gt; x.Home.City));\n        Assert.AreEqual(&quot;Home.FlatNumber&quot;,\n            PropertyName.For&lt;person&gt;(x =&gt; x.Home.FlatNumber));\n    }\n}\n\npublic class Person\n{\n    public string Name { get; set; }\n    public int Age { get; set; }\n    public Home Home { get; set; }\n}\n\npublic class Home\n{\n    public string City { get; set; }\n    public string FlatNumber { get; set; }\n}\n<\/pre>\n<p>Implementation uses .NET 3.5 feature called expression trees. Expression trees represent language-level code in the form of data. The data is stored in a tree-shaped structure.<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n\/\/\/ &lt;summary&gt;\n\/\/\/ Gets property name using lambda expressions.\n\/\/\/ &lt;\/summary&gt;\ninternal class PropertyName\n{\n    public static string For&lt;t&gt;(\n        Expression&lt;func&lt;t, object&gt;&gt; expression)\n    {\n        Expression body = expression.Body;\n        return GetMemberName(body);\n    }\n\n    public static string For(\n        Expression&lt;func&lt;object&gt;&gt; expression)\n    {\n        Expression body = expression.Body;\n        return GetMemberName(body);\n    }\n\n    public static string GetMemberName(\n        Expression expression)\n    {\n        if (expression is MemberExpression)\n        {\n            var memberExpression = (MemberExpression)expression;\n\n            if (memberExpression.Expression.NodeType ==\n                ExpressionType.MemberAccess)\n            {\n                return GetMemberName(memberExpression.Expression)\n                    + &quot;.&quot;\n                    + memberExpression.Member.Name;\n            }\n            return memberExpression.Member.Name;\n        }\n\n        if (expression is UnaryExpression)\n        {\n            var unaryExpression = (UnaryExpression)expression;\n\n            if (unaryExpression.NodeType != ExpressionType.Convert)\n                throw new Exception(string.Format(\n                    &quot;Cannot interpret member from {0}&quot;,\n                    expression));\n\n            return GetMemberName(unaryExpression.Operand);\n        }\n\n        throw new Exception(string.Format(\n            &quot;Could not determine member from {0}&quot;,\n            expression));\n    }\n}\n<\/pre>\n<p><em>UnaryExpression<\/em> part is needed for value types to work.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The whole idea is simple, we want this test to pass: &#x5B;Test] void CanGetPropertyName_UsingLambda() { Assert.AreEqual(&quot;Name&quot;, PropertyName.For&lt;person&gt;(x =&gt; x.Name)); } It seams nice and convenient way of getting property name. Whole test fixture looks as follows: &#x5B;TestFixture] public class PropertyNameTests { public string NameForTest { get; set; } &#x5B;Test] public void CanGetPropertyName_SameType_UsingLambda() { Assert.AreEqual(&quot;NameForTest&quot;, PropertyName.For(() [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[6],"tags":[15],"class_list":["post-472","post","type-post","status-publish","format-standard","hentry","category-programming","tag-c"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.limilabs.com\/blog\/wp-json\/wp\/v2\/posts\/472"}],"collection":[{"href":"https:\/\/www.limilabs.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.limilabs.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.limilabs.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.limilabs.com\/blog\/wp-json\/wp\/v2\/comments?post=472"}],"version-history":[{"count":0,"href":"https:\/\/www.limilabs.com\/blog\/wp-json\/wp\/v2\/posts\/472\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.limilabs.com\/blog\/wp-json\/wp\/v2\/media?parent=472"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.limilabs.com\/blog\/wp-json\/wp\/v2\/categories?post=472"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.limilabs.com\/blog\/wp-json\/wp\/v2\/tags?post=472"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}