2009-02-27 7 views
1

私は、継承階層を持つクラスをマッピングする状況があります。私は、各クラスが必要とする項目のリストを持っています。例えば:私はいくつかの解決策を考えることができますが、彼らは非常に複雑に見えるC#のサブクラスからプロパティを集約するうえで、どのような方法がありますか?

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

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

私はこのようなスーパークラスのすべての集計を返すメソッド呼び出しをしたいと思い。私はそれが私が行方不明になっている上品な解決策があるように感じる。誰も助けることができますか?

ありがとうございます!

答えて

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

。偉大な議論の男の子、ありがとう! –

+0

Union()はどこから来たのですか? System.ArrayはIEnumerableを実装しているので、それは利用可能ですか? –

+0

はい、IEnumerable のLinq拡張メソッドの1つです。 – BFree

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

私は単純なアプローチのために行くだろう:4分以内に受け入れ

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.)

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"); 
    } 
} 
関連する問題