2009-02-27 37 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"); 
    } 
} 
相关问题