2016-08-05 36 views
1
  • C是一些类与DisplayNameAttribute
  • GetDisplayName方法返回指定属性成员
  • .NET3.5的DisplayNameAttribute参数属性成员,Unity3D

我的问题是实现真是多余因为SequenceEqual方法需要指定的类型参数,所以我应该为每个可能的属性类型实现IF代码块。有什么反射黑魔法可以让我的代码更清洁?最简单的方法来比较对象与C#中PropertyInfo.GetValue的结果?

public class C 
{ 
    [DisplayName("M1")] 
    public List<string> M1 { get; set; } 
    [DisplayName("M2")] 
    public List<string> M2 { get; set; } 
    [DisplayName("M3")] 
    public string M3 { get; set; } 
    [DisplayName("M4")] 
    public List<int> M4 { get; set; } 
    //There can be many property members with different type 
    //M5 
    //... 
    //... 
    //M99 
} 

public void GetCMemberDisplayName() 
{ 
    var c = new C 
    { 
     M1 = new List<string> {"a"}, 
     M2 = new List<string>(), 
     M3 = "b", 
     M4 = new List<int>() 
    }; 
    var nameOfM1 = GetDisplayName(c, c.M1);//"M1" 
    var nameOfM2 = GetDisplayName(c, c.M2);//"M2" 
    var nameOfM3 = GetDisplayName(c, c.M3);//"M3" 
} 

//EDIT, add another situation, instance and its property member could be input parameters 
public string AnotherGetMemberDisplay(object instance, object member) 
{ 
    return GetDisplayName(instance, member); 
} 

private static string GetDisplayName(object instance, object member) 
{ 
    var propertyInfos = instance.GetType() 
     .GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance 
         | BindingFlags.GetField | BindingFlags.GetProperty) 
     .FindAll(pi => pi.IsDefined(typeof(DisplayNameAttribute), true)); 


    foreach (var propertyInfo in propertyInfos) 
    { 
     var value = propertyInfo.GetValue(instance, null); 

     //Very nasty code below, need implement all IF code for each type of property member 
     if (member.GetType() == typeof(List<string>) && value.GetType() == typeof(List<string>)) 
     { 
      if ((value as List<string>).SequenceEqual(member as List<string>)) 
      { 
       return (propertyInfo.GetCustomAttributes(true).ToList() 
        .Find(a => (a as DisplayNameAttribute) != null) as DisplayNameAttribute) 
        .DisplayName; 
      } 
     } 
     else if (member.GetType() == typeof(List<int>) && value.GetType() == typeof(List<int>)) 
     { 
      if ((value as List<int>).SequenceEqual(member as List<int>)) 
      { 
       return (propertyInfo.GetCustomAttributes(true).ToList() 
        .Find(a => (a as DisplayNameAttribute) != null) as DisplayNameAttribute) 
        .DisplayName; 
      } 
     } 
     else 
     { 
      if (value == member) 
      { 
       return (propertyInfo.GetCustomAttributes(true).ToList() 
        .Find(a => (a as DisplayNameAttribute) != null) as DisplayNameAttribute) 
        .DisplayName; 
      } 
     } 


    } 

    throw new Exception("No DisplayNameAttributes Applied."); 
} 

回答

0

我会建议实施沿着这些路线的方法来获得的MemberInfo为所需的属性:

public MemberInfo GetMemberInfo<T>(Expression<Func<T>> memberLambda) 
{ 
    var memberExpression = memberLambda.Body as MemberExpression; 

    if (memberExpression == null) 
    { 
     throw new ArgumentException("You must pass a lambda of the form: '() => Class.Member' or '() => object.Member'"); 
    } 

    return memberExpression.Member; 
} 

(从提问者的解决方案在这里得到:Get name of property as a string

然后获取属性值如此简单:

public void GetCMemberDisplayName() 
{ 
    var c = new C 
    { 
     M1 = new List<string> {"a"}, 
    }; 

    var m1MemberInfo = GetMemberInfo(() => c.M1); 
    var nameOfM1 = GetDisplayName(m1MemberInfo); 
} 

private string GetDisplayName(MemberInfo memberInfo) 
{ 
    var displayNameAttribute = memberInfo.GetCustomAttribute(typeof(DisplayNameAttribute)); 

    if (displayNameAttribute != null) 
    { 
     return displayNameAttribute.DisplayName; 
    } 
    else 
    { 
     throw new Exception("No DisplayNameAttributes Applied."); 
    } 
} 

I'v e避免使用C#6代码,因为您最初将您的帖子标记为Unity3D,它使用的编译器目前不支持C#6.如果您使用支持它的编译器,则该过程更简单(不再支持需要GetMemberInfo法):

public void GetCMemberDisplayName() 
    { 
     var c = new C 
     { 
      M1 = new List<string> {"a"}, 
     }; 

     var nameOfM1 = GetDisplayName(typeof(C), nameof(c.M1)); 
    } 


private static string GetDisplayName(Type ownerType, string propertyName) 
{ 
    var propertyInfo = ownerType.GetProperty(propertyName); 

    var displayNameAttribute = propertyInfo.GetCustomAttribute(typeof(DisplayNameAttribute)); 

    if (displayNameAttribute != null) 
    { 
     return displayNameAttribute.DisplayName; 
    } 
    else 
    { 
     throw new Exception("No DisplayNameAttributes Applied."); 
    } 
} 
+0

感谢您的回答,您的解决方案实例化一个对象的时候,然后打电话给你提供的方法的工作原理。但是,在我的真实世界中,我通过PropertyInfo.GetValue获取了实例及其成员,这意味着我无法使用Class.Member表达式来获取正确的MemberInfo。你能修改你的代码来满足这种情况吗? –