C# - 如何创建一个具有共同属性的不同类的数组?

时间:2017-06-30 23:36:21

标签: c# .net arrays generics

我有一个名为PersonActivity的C#类。它包含唯一的Id(int),PersonId(int)和ActivityType(字符串)。

我有另一个继承自PersonActivity的类HighlightedActivity。我需要做的是将一个数组HighlightedActivity []称为"活动",我已经完成了。我的问题是我如何制作这个数组,但基于ActivityType的某些附加属性?

我的目的是遍历"活动" HighlightedActivity类型,然后设置基于ActivityType的其他属性。活动类型类似于具有ISBN编号的书籍,而期刊具有卷和发行编号,而奖励具有金额。它们都具有PersonActivity类的Id,PersonId和ActivityType。我不确定HighlightedActivity类应该是什么样子,以便我可以将所有这些项放在同一个列表中。

阵列"活动"应该是这样的:

[0] {Id = 2,PersonId = 5,ActivityType =" Book",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 =" Grant",Amount = 444.00}

2 个答案:

答案 0 :(得分: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;
    }
}

您还可以按活动类型和投射活动切换到适当的班级。

答案 1 :(得分: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);
    }
}