2017-06-30 9 views
0

私はPersonActivityと呼ばれるC#クラスを持っています。これは一意のId(int)、PersonId(int)、およびActivityType(文字列)を保持します。共通のプロパティを共有する異なるクラスの配列を作成するにはどうすればよいですか?

PersonActivityを継承する別のクラスHighlightedActivityがあります。私がやる必要があるのは、配列 "HighlightedActivity []"を "activities"と呼ぶことです。私の質問は、どのように私はこの1つの配列を作ることができますが、ActivityTypeに基づいて特定のプロパティを追加してですか?

私の意図は、HighlightedActivityタイプの "activities"をループし、ActivityTypeに基づいて追加のプロパティを設定することです。アクティビティタイプはISBN番号の本のようなもので、ジャーナルはボリューム番号と発行番号、金額は金額です。それらはすべてPersonActivityクラスのId、PersonId、およびActivityTypeを持っています。私はHighlightedActivityクラスがどのようなものかを確認していないので、これらのアイテムをすべて同じリストに入れることができます。

アレイ "活動" のようになります

[0] {ID = 2、PERSONID = 5、ActivityTypeを= "ブック"、ISBN = "13239382"}

[1] {ID = 3、PersonId = 5、ActivityType = "Journal"、Volume = 5、Issue = 124}

[2] {Id = 4、PersonId = 5、ActivityType = "Journal"、Volume = 8、Issue = 201}

[3] {Id = 5、PersonId = 5、ActivityType = "Journal"、Volume = 8、Issue = 202}

[4] {ID = 6、PERSONID = 5、ActivityTypeを= "グラント"、金額= 444.00}

答えて

0

基本アクティビティクラスを作成し、そこから他のオブジェクトを継承することができます。基本クラスには、アクティビティーのタイプを追跡するために使用できるアクティビティー・タイプがあります。

は、列挙型としてこれを定義します。

public enum ActivityType 
{ 
    Book, 
    Journal, 
    Grant 
} 

あなたのベースクラスは、共通のプロパティを保持します。また、アクティビティタイプと配列から派生クラスを作成するコンストラクタも用意されています。配列ベースのコンストラクタを使用するので、配列の長さを検証し、配列オブジェクトを正しい型に変換するために使用できる保護されたメンバーを追加します。

public abstract class Activity 
{ 
    public int Id { get; set; } 
    public int PersonId { get; set; } 
    public ActivityType ActivityType { get; private set; } // consider to use enum 

    public Activity(ActivityType activityType) 
    { 
     ActivityType = activityType; 
    } 
    public Activity(object[] values) 
    { 
     if (values.Length < 4) 
      throw new ArgumentException(); 

     this.Id = getInt(values[0]); 
     this.PersonId = getInt(values[1]); 
     this.ActivityType = getActivityType(values[2]); 
    } 
    protected int getInt(object value) 
    { 
     if (!(value is int)) 
     { 
      throw new ArgumentException(); 
     } 
     return (int)value; 
    } 
    protected string getString(object value) 
    { 
     if (!(value is string)) 
     { 
      throw new ArgumentException(); 
     } 
     return (string)value; 
    } 
    protected decimal getDecimal(object value) 
    { 
     if (!(value is decimal)) 
     { 
      throw new ArgumentException(); 
     } 
     return (decimal)value; 
    } 
    protected ActivityType getActivityType(object value) 
    { 
     ActivityType result; 
     if(value is string) 
     { 
      if (!Enum.TryParse((string)value, out result)) 
      { 
       throw new ArgumentException(); 
      } 
     } 
     else if(value is ActivityType) 
     { 
      result = (ActivityType)value; 
     } 
     else 
     { 
      throw new ArgumentException(); 
     } 
     return result; 
    } 
} 

現在、必要に応じて基本プロパティを設定する基本コンストラクタを呼び出す派生クラスを定義します。配列のコンストラクタでは、配列の長さを検証し、配列のオブジェクトを正しい型に変換するために基本メソッドを使用します。

public class Book : Activity 
{ 
    public Book() : base(ActivityType.Book) { } 
    public Book(object[] values) : base(values) 
    { 
     if (values.Length != 4) throw new ArgumentException(); 
     this.ISBN = getString(values[3]); 
    } 
    public string ISBN { get; set; } 
} 

public class Journal : Activity 
{ 
    public Journal() : base(ActivityType.Journal) { } 
    public Journal(object[] values) : base(values) 
    { 
     if (values.Length != 5) throw new ArgumentException(); 
     this.Volume = getInt(values[3]); 
     this.Issue = getInt(values[4]); 
    } 

    public int Volume { get; set; } 
    public int Issue { get; set; } 
} 

public class Grant : Activity 
{ 
    public Grant() : base(ActivityType.Grant) { } 
    public Grant(object[] values) : base(values) 
    { 
     if (values.Length != 4) throw new ArgumentException(); 
     this.Volume = getDecimal(values[3]); 
    } 
    public decimal Volume { get; set; } 

} 

最後に、ファクトリパターンを使用して、配列の配列またはアクティビティのリストからアクティビティを作成するクラスを作成します。ファクトリには、上で定義したデータをテストするメソッドもあります。

public class ActivityFactory 
{ 
    public static List<Activity> GetActivities(object[][] values) 
    { 
     List<Activity> result = new List<Activity>(); 
     for (int i = 0; i < values.Length; i++) 
     { 
      result.Add(MakeActivity(values[i])); 
     } 
     return result; 
    } 
    static Activity MakeActivity(object[] values) 
    { 
     Activity result = null; 
     switch (values[2].ToString()) 
     { 
      case "Book": 
       result = new Book(values); 
       break; 
      case "Journal": 
       result = new Journal(values); 
       break; 
      case "Grant": 
       result = new Grant(values); 
       break; 
      default: 
       throw new ArgumentException("Invalid activity " + values[2].ToString()); 

     } 
     return result; 
    } 
    public static void RunTest() 
    { 
     object[][] values = new object[][] { 
      new object[] { 2, 5, "Book", "13239382"}, 
      new object[] { 3, 5, "Journal", 5, 124}, 
      new object[] { 4, 5, "Journal", 8, 201}, 
      new object[] { 5, 5, "Journal", 8, 202}, 
      new object[] { 6, 5, "Grant", 444.00m} 
     }; 
     List<Activity> activities = GetActivities(values); 
    } 
} 
+0

ありがとう!それは私が必要なもののように見えます。ここでは、それらをループし、そのタイプに基づいてプロパティを割り当てています。 ActivityTypeあたりのカスタム値を前もって用意していないので、コードの一部に乗ることさえできるかもしれないと思います。 https://dotnetfiddle.net/dXmwwK – Andy

+0

ようこそ。あなたの問題は、.netの一般的な使用例であり、Factory Patternは、ロジックをクリーンに保ちながら、そのようなユースケースを処理する良い方法です。あなたはそれがあなたを助けたことを知っているので、回答を受け入れたものとしてマークすることができます。 –

3
あなたは基本アクティビティクラス(あなたがいない場合活動読み取り専用の値オブジェクトを作成することも考慮を作成することができます

public abstract class Activity 
{ 
    public int Id { get; set; } 
    public int PersonId { get; set; } 
    public string ActivityType { get; private set; } // consider to use enum 

    public Activity(string activityType) 
    { 
     ActivityType = activityType; 
    } 
} 

そして、この基本クラスを継承するカスタムアクティビティのクラスを作成::)を作成した後、それらを変更しようとして

public class Book : Activity 
{ 
    public Book() : base("Book") { } 

    public string ISBN { get; set; } 
} 

public class Journal : Activity 
{ 
    public Journal() : base("Journal") { } 

    public int Volume { get; set; } 
    public int Issue { get; set; } 
} 

とベースタイプの活動のリストを保持:

var activities = new List<Activity> { 
    new Book { Id = 2, PersonId = 5, ISBN = "13239382" }, 
    new Journal { Id = 3, PersonId = 5, Volume = 5, Issue = 124 }, 
    new Journal { Id = 4, PersonId = 5, Volume = 8, Issue = 201 }, 
    new Journal { Id = 5, PersonId = 5, Volume = 8, Issue = 202 } 
    // etc 
}; 

その後、あなたは適切な型に各アクティビティをキャストし、そのプロパティ(C#7パターンマッチングとサンプル)を取得することができます。

foreach(var activity in activities) 
{ 
    switch(activity) 
    { 
     case Book book: 
      /* use book here */ 
      break; 
     case Journal journal: 
      /* use journal here */ 
      break; 
     default: 
      /* handle unknown activity */ 
      break; 
    } 
} 

ます。また、適切なクラスに活動タイプとキャスト活動によって切り替えることができます。

+0

ありがとうございます!私はそれのような活動の配列を宣言することができたことを理解していませんでした。これは私が必要なもののように見えます:) – Andy

関連する問題