如何重新访问强类型的给定类型的属性名称?

时间:2015-03-09 13:51:36

标签: system.reflection

如何简化下面的代码以避免在泛型方法上传递类型推断的对象?

using System;
using System.Linq.Expressions;

namespace lambda
{
    class Program
    {
        static void Main(string[] args)
        {

            var area = new Area { Name = "New Area" };
            var propertyName = area.GetPropertyName(area, a => a.Name); // propertyName is COMPILE time checked

            Console.WriteLine(propertyName);

        }
    }

    public class Area
    {
        public int Id;
        public string Name { get; set; }
    }

    public static class Extension
    {
        public static string GetPropertyName<T>(this Area entity, T e, Expression<Func<T, object>> path) // T e for type inference
        {
            var member = path.Body as MemberExpression;
            if (member == null) throw new ArgumentException();
            return member.Member.Name;
        }
    }
}

我的意思是代替使用area.GetPropertyName(area,a =&gt; a.Name)调用扩展方法  只是像这个区域一样调用.GetPropertyName(a =&gt; a.Name),避免仅为类型推断传递区域对象

我想除非我将方法的签名重构为GetPropertyName(此IEntity实体,Expression&gt; path),否则我无法做到 但是在那种情况下,我希望在编写代码时不太想要,因为我需要在每次调用时指定类型 我的意思是area.GetPropertyName(a =&gt; a.Name)似乎对我来说不像编写区域那么清晰.GetPropertyName(area,a =&gt; a.Name)

1 个答案:

答案 0 :(得分:0)

下面的示例代码适用于要求的要求,在调用扩展方法时无需传递对象本身以进行类型推断 我使用了一个基类和一个接口,对于我的所有域类都可以正常工作。 见下面的代码

namespace UnitTestProject
{
    using Microsoft.VisualStudio.TestTools.UnitTesting;
    using System;
    using System.Linq.Expressions;

    public interface IEntity<T>
    {
    }

    public abstract class Entity<T> : IEntity<T> where T : class
    {
    }

    public class Area : Entity<Area>
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public DateTime Created { get; set; }
        public bool Closed { get; set; }
        public string Description { get; set; }
    }

    public static class EntityExtension
    {
        public static string GetPropertyName<T>(this IEntity<T> entity, Expression<Func<T, object>> expr) // T e for type inference
        {
            var unary = expr.Body as UnaryExpression;
            var member = expr.Body as MemberExpression;
            return member != null ? member.Member.Name : (unary != null ? ((MemberExpression)unary.Operand).Member.Name : String.Empty);
        }
    }


    [TestClass]
    public class UnitTest
    {
        [TestMethod]
        public void GetPropertyName_Tests()
        {
            var area = new Area();

            var x = area.GetPropertyName(a => a.Id);
            var y = area.GetPropertyName(a => a.Name);
            var v = area.GetPropertyName(a => a.Created);
            var w = area.GetPropertyName(a => a.Closed);
            var z = area.GetPropertyName(a => a.Description);

            Assert.AreEqual(x, "Id");
            Assert.AreEqual(y, "Name");
            Assert.AreEqual(v, "Created");
            Assert.AreEqual(w, "Closed");
            Assert.AreEqual(z, "Description");

        }
    }
}