Создать класс MyItem для классификации по типу - PullRequest
1 голос
/ 05 мая 2019

У меня есть следующий код, когда я объявляю MyItem, он будет автоматически добавлен в Roster.

public class MyItem
{
    private static Dictionary<string, string> Roster;

    public static bool addToRoster(MyItem item)
    {
        if (Roster.ContainsKey(item.code))
            return false;

        Roster.Add(item.code, item.description);

        return true;
    }

    public string code { get; protected set; }
    public string description { get; protected set; }

    public MyItem(string _code, string _desc)
    {
        code = _code;
        description = _desc;
        addToRoster(this);
    }
}

Поэтому, когда я использую его, как показано ниже, словарь Roster будет содержать 2 значения:

MyItem itema = new MyItem("code1", "desc1");
MyItem itemb = new MyItem("code2", "desc2");
MyItem itemc = new MyItem("code1", "desc1");

Пока все хорошо. Теперь у меня может быть несколько реестров, основанных на разных типах. Например, у меня могут быть Subject, Room и Building. Я не хочу объявлять несколько классов, производных от класса MyItem, это будет слишком много. Конечно, я могу добавить свойство

string RosterType { get; set; }

в MyItem классе, но это создаст кучу избыточности данных.

Я думаю, что, может быть, я могу использовать атрибут, но кажется, что атрибут нельзя использовать на объекте.

Я пытаюсь найти что-то вроде этого

[RosterType("Room")]
MyItem item1("WJ203", "Room WJ203");

[RosterType("Subject")]
MyItem item2("MATH01", "Basic Math");

и измените Реестр на

private static Dictionary<string, Dictionary<string, string>> Rosters;

Затем я могу добавить предметы в разные списки на основе разных RosterType. Но, похоже, я не могу установить атрибут объекта.

Что я должен сделать, чтобы заархивировать свою цель? Любая хорошая мысль?

Позвольте мне добавить некоторые детали

Данные, которые я получил, похожи на:

{
    result: [ 
    {
        "propA": { "code":"XXX", "desc":"XXX" },
        "propB": { "code":"XXX", "desc":"XXX" },
        "propC": { "code":"XXX", "desc":"XXX" }
    },
    {
        "propA": { "code":"XXX", "desc":"XXX" },
        "propB": { "code":"XXX", "desc":"XXX" },
        "propC": { "code":"XXX", "desc":"XXX" }
    },
    {
        "propA": { "code":"XXX", "desc":"XXX" },
        "propB": { "code":"XXX", "desc":"XXX" },
        "propC": { "code":"XXX", "desc":"XXX" }
    }]
}

Существует много разных типов результатов, и большинство из них представляют собой комбинации разных типов реквизита. все реквизиты в формате cod - desc. Я знаю, что это плохой дизайн, но я ничего не могу сделать со своей стороны. Мне нужно сохранить результат в разные таблицы, просто с кодом; а также необходимо сохранить весь код в разных таблицах кода. Все это должно быть сделано во время деарелизации. так что я прыгаю, чтобы сделать это в классе MyItem. Процедура категоризации может происходить в OnDesearlization. Так что для части результата я могу легко настроить свой класс на основе другого типа результата.

1 Ответ

0 голосов
/ 05 мая 2019

Идея состоит в том, чтобы установить атрибут для свойств. Иметь класс ResultBase, который будет проходить через атрибуты, и, если найден элемент Ростера, разобраться с ним. Поэтому, как только все это будет сделано, мне просто нужно объявить свои разные результаты без дополнительного кодирования ...

using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.Reflection;

namespace RosterNS
{
    using IRoster = IDictionary<string, string>;

    [DataContract]
    public class RosterItem
    {
        [DataMember]
        public string code { get; set; }

        [DataMember]
        public string description { get; set; }
    }

    public class Rosters
    {
        static private Dictionary<string, IRoster> rosters = new Dictionary<string, IRoster>();
        public static IRoster RegisterRoster(string category)
        {
            IRoster roster;

            if (!rosters.TryGetValue(category, out roster))
            {
                roster = new Dictionary<string, string>();
                rosters.Add(category, roster);
            }

            return roster;
        }
#if DEBUG
        public static void ListRosters()
        {
            foreach(KeyValuePair<string, IRoster> kvp in rosters)
            {
                Console.WriteLine("Category:{0}", kvp.Key.ToString());
                foreach (KeyValuePair<string, string> skvp in kvp.Value)
                    Console.WriteLine("\t{0:20}==>{1}", skvp.Key, skvp.Value);
            }
        }
#endif
    }

    [AttributeUsage(AttributeTargets.Property)]
    public class RosterCategoryAttribute : Attribute
    {
        private IRoster roster;
        public string Category { get; protected set; }

        public RosterCategoryAttribute(string category)
        {
            Category = category;
            roster = Rosters.RegisterRoster(category);
        }

        public void addToRoster(RosterItem item)
        {
            if (item != null && !roster.ContainsKey(item.code))
                roster.Add(item.code, item.description);
        }
    }

    [DataContract]
    public class RosterResult
    {
        //The only implementation that save the RosterItem into categorized Roster
        [OnDeserialized]
        public void OnDeserialized(StreamingContext sc)
        {
            PropertyInfo[] properties = GetType().GetProperties();

            foreach (PropertyInfo info in properties)
            {
                RosterCategoryAttribute attr = info.GetCustomAttribute<RosterCategoryAttribute>();
                if (attr != null)
                    attr.addToRoster(info.GetValue(this) as RosterItem);
            }
        }
    }
}

Чтобы использовать его, мне нужно объявить свой результат примерно так

namespace MyResult
{
    [DataContract]
    public class ResultType1 : RosterResult
    {
        [DataMember]
        [RosterCategory("Location")]
        public RosterItem location { get; protected set; }

        [DataMember]
        [RosterCategory("Status")]
        public RosterItem status { get; protected set; }
    }

    [DataContract]
    public class ResultType2 : RosterResult
    {
        [DataMember]
        [RosterCategory("Location")]
        public RosterItem location { get; protected set; }

        [DataMember]
        [RosterCategory("Equipment")]
        public RosterItem equipment { get; protected set; }

        [DataMember]
        public string Name { get; protected set; }
    }
}

Таким образом, после множества десериализаций реестр будет заполнен уникальной парой код-спецификация, основанной на разных категориях.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...