2009-02-27 59 views
1

我有一種情況,我映射具有繼承層次結構的類。我有一個每個班級都知道它需要的項目清單。例如:什麼是從C#中的子類中聚合屬性的優雅方法?

public class PersonMapper 
{ 
    private string[] attributes = new[] {"firstName", "lastName"}; 
} 

public class UserMapper : PersonMapper 
{ 
    private string[] attributes = new[] {"username"}; 
} 

public class EmployeeMapper : PersonMapper 
{ 
    private string[] attributes = new[] {"employeeId"}; 
} 

我想就返回所有的超類的這樣的聚合方法調用:

EmployeeMapper mapper = new EmployeeMapper(); 
string[] attributes = mapper.GetAttributes(); 
Assert.That(attributes, Has.Member("firstname")); 

我能想到的一些解決方案,但他們似乎過於複雜。我覺得我缺少一個優雅的解決方案。誰能幫忙?

在此先感謝!

回答

3

您可以在超類上有一個稱爲GetAttributes的虛方法/屬性,它返回專用數組。然後,在每個子類中,像這樣覆蓋它。首先調用基本的GetAttribute方法來獲取基類數組,以及與子類數組的組合,並返回新數組。

代碼示例:

public class PersonMapper 
    { 
     private string[] attributes = new[] { "firstName", "lastName" }; 
     public virtual string[] GetAttributes() 
     { 
      return attributes; 
     } 
    } 

public class EmployeeMapper : PersonMapper 
    { 
     private string[] attributes = new[] { "employeeId" }; 
     public override string[] GetAttributes() 
     { 
      return base.GetAttributes().Union(this.attributes).ToArray(); 
     } 
    } 
+0

接受4分鐘內。大討論男孩,謝謝! – 2009-02-27 17:43:38

0

沒有反思,沒有辦法做到這一點在當前狀態下。你可以做的是做一個受保護的虛擬方法,它允許每個類將它們的屬性添加到列表中並以這種方式進行聚合。

public class PersonMapper { 
    protected virtual void AggregateAttributes(List<string> list) { 
    list.AddRange(attributes); 
    } 
    public List<string> GetAttributes() { 
    List<string> list = new List<string>(); 
    AggregateAttributes(list); 
    return list; 
    } 
} 

public class UserMapper { 
    protected override void AggergateAttributes(List<string> list) { 
    base.AggregateAttributes(list); 
    list.AddRange(attributes); 
    } 
} 

public class EmployeeMapper { 
    protected override void AggergateAttributes(List<string> list) { 
    base.AggregateAttributes(list); 
    list.AddRange(attributes); 
    } 
} 
1

我會忍不住開發被應用到每一個我在乎跟蹤,然後利用反射與應用該屬性枚舉屬性的屬性的自定義屬性。您可以使用延遲加載,以便僅填充一次屬性列表。我也可能使GetAttributes()成爲靜態(類)方法。

public class MappedAttribute : Attribute 
{ 
} 

public class Person 
{ 
    [Mapped] 
    public string FirstName { get; set; } 

    [Mapped] 
    public string LastName { get; set; } 

    public string DisplayName 
    { 
     get { return FirstName + " " + LastName; } 
    } 
} 

public static class Mapper 
{ 
    public static IList<string> Attributes(Type t) 
    { 
      List<string> attributes = new List<string>(); 

      foreach (PropertyInfo pInfo in t.GetProperties()) 
      { 
       MappedAttribute attr = pInfo.GetCustomAttributes(typeof(MappedAttribute),false) 
              .Cast<MappedAttribute>() 
              .FirstOrDefault(); 
       if (attr != null) 
       { 
        attributes.Add(pInfo.Name); 
       } 
      } 

      return attributes; 
    } 
} 
0

我會去一個更簡單的方法:

class Entity { 
    public virtual IEnumerable<string> Attributes { get { yield return "Name"; } } 
} 

class Person : Entity { 
    public override IEnumerable<string> Attributes { 
     get { 
      return new string[] { "FirstName", "LastName" } 
       .Concat(base.Attributes); 
     } 
    } 
} 

class User : Person { 
    public override IEnumerable<string> Attributes { 
     get { 
      return new string[] { "UserName" } 
       .Concat(base.Attributes); 
     } 
    } 
} 

(附註:這些類型的層次結構很少在單繼承語言工作了。)

0
public class PersonMapper 
{ 
    protected List<string> attributes = 
     new List<string>() {"firstName", "lastName"}; 
    public string[] GetAttributes() 
    { 
     //defensive copy 
     return attributes.ToArray(); 
    } 
} 

public class EmployeeMapper : PersonMapper 
{ 
    public EmployeeMapper() 
    { 
     attributes.Add("employeeId"); 
    } 
} 
相關問題