我遇到的情况是我正在映射具有继承层次结构的类。我有一个每个类都知道它需要的项目列表。例如:
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"));
我可以想到一些解决方案,但它们似乎过于复杂。我觉得有一个优雅的解决方案,我错过了。有人可以帮忙吗?
提前致谢!
答案 0 :(得分: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();
}
}
答案 1 :(得分: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;
}
}
答案 2 :(得分: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);
}
}
答案 3 :(得分: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);
}
}
}
(P.S。这种层次结构很少用单继承语言来解决。)
答案 4 :(得分: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");
}
}