2016-08-05 41 views
1
  • C ist einige Klasse hat die Eigenschaft Mitglieder mit Displayname
  • GetDisplayName Methode gibt den Parameter Displayname der angegebenen Eigenschaft Mitglied
  • NET3.5, Unity3D

Mein Problem ist die Umsetzung ist wirklich überflüssig Weil die Methode SequenceEqual angegebene Typparameter benötigt, sollte ich IF-Codeblocks für jeden möglichen Eigenschaftstyp implementieren. Gibt es eine Reflexion? Schwarze Magie kann meinen Code sauberer machen?Einfachster Weg, um Objekt mit dem Ergebnis von PropertyInfo.GetValue in C# zu vergleichen?

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."); 
} 

Antwort

0

Ich würde vorschlagen, ein Verfahren in dieser Richtung der Umsetzung des Member für die gewünschte Eigenschaft zu erhalten:

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; 
} 

(abgeleitet aus der Lösung der Fragesteller hier: Get name of property as a string)

den Attributwert Dann erwerben ist so einfach wie folgt:

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 Es wurde vermieden, C# 6-Code zu verwenden, da Ihr Post ursprünglich als Unity3D gekennzeichnet war, das einen Compiler verwendet, der C# 6 derzeit nicht unterstützt. Wenn Sie einen Compiler verwenden, der dies unterstützt, ist der Prozess einfacher (Sie nicht mehr) benötigen Sie die GetMemberInfo-Methode):

+0

Dank für Sie beantworten, funktioniert Ihre Lösung bei der Instanziierung eines Objekts und dann rufen Sie die Methoden, die Sie zur Verfügung gestellt. In meiner realen Welt habe ich die Instanz und ihr Member jedoch über PropertyInfo.GetValue erhalten, was bedeutet, dass ich den Class.Member-Ausdruck nicht verwenden kann, um die richtige MemberInfo zu erhalten. Können Sie Ihren Code ändern, um diese Situation zu erfüllen? –