В C# есть ли способ свести эти 1 Список и два Словаря к одной коллекции, возможно, используя отражение? - PullRequest
0 голосов
/ 30 апреля 2020

В настоящее время у меня есть следующий код:

using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;

namespace MyNamespace{
    using AddFunction = Func<MyDictionary, object, MyDictionary>;

    class MyDictionary {
        public const string AFile = "a.xml";
        public const string BFile = "b.xml";
        public const string CFile = "c.xml";
        public const string DFile = "d.xml";

        private static readonly List<string> fileList = new List<string> { AFile, BFile, CFile, DFile };

        public static readonly Dictionary<string, Type> documentTypeByFileName = new Dictionary<string, Type> {
            {AFile, typeof(ADocument)},
            {BFile, typeof(BDocument)},
            {CFile, typeof(CDocument)},
            {DFile, typeof(DDocument)},
        };

        private static readonly Dictionary<string, AddFunction> functionByFileName = new Dictionary<string, AddFunction> {
                {AFile, (@this, obj) => @this.AddA((A)obj)},
                {BFile, (@this, obj) => @this.AddB((B)obj)},
                {CFile, (@this, obj) => @this.AddC((C)obj)},
                {DFile, (@this, obj) => @this.AddD((D)obj)}
        };

        private Dictionary<string, MyCollection> collectionByWidgetId = new Dictionary<string, MyCollection>();

        public MyDictionary(Dictionary<string, object> dataByFileNames) {
            fileList.ForEach(fileName => this.AddData(fileName, dataByFileNames));
        }  

        private MyDictionary AddData(string fileName, Dictionary<string, object> dataByFileNames) {
            ((DataListable)dataByFileNames[fileName]).GetList()
                .ForEach(item => functionByFileName[fileName](this, item));
            return this;
        }

        private MyDictionary AddA(A a) {
            this.collectionByWidgetId.Add(a.widgetId, new MyCollection(a));
            return this;
        }

        private MyDictionary AddB(B b) {
            this.collectionByWidgetId[b.widgetId].b = b;
            return this;
        }

        private MyDictionary AddC(C c) {
            this.collectionByWidgetId[c.widgetId].cList.Add(c);
            return this;
        }

        private MyDictionary AddD(D d) {
            this.collectionByWidgetId[d.widgetId].dList.Add(d);
            return this;
        }
    }   
}

Как видите, он содержит 3 разные коллекции.

Нам нужно fileList для поддержания порядка.

Нам нужно documentTypeByFileName, чтобы получить тип объекта C#, которому будет сопоставлено содержимое файлов. Каждый из них является просто оболочкой для списка типа, который можно предсказать по имени (например, содержимое ADocument будет просто списком). Итак, каждый из этих типов документов реализует:

    interface DataListable {
        List<object> GetList();
    }

documentTypeByFileName используется в другом классе следующим образом:

        private static Dictionary<string, object> DownloadFiles(IConfigurationRoot config) {
            Dictionary<string, object> dataListByFileNames = new Dictionary<string, object>();
            ShipmentCollectionDictionary.documentTypeByFileName.Keys.ToList()
                .ForEach(name => dataListByFileNames.Add(name, DownloadData(name, config)));
            return dataListByFileNames;
        }

        private static object DownloadData(string name, IConfigurationRoot config) {
            return new XmlSerializer(ShipmentCollectionDictionary.documentTypeByFileName[name], new XmlRootAttribute("Document"))
                .Deserialize(new StringReader(DownloadFromBlobStorage(name, config).ToString()));
        }

        private static CloudBlockBlob DownloadFromBlobStorage(string filetoDownload, IConfigurationRoot config) {
            return CloudStorageAccount.Parse(config["AzureWebJobsStorage"])
                .CreateCloudBlobClient()
                .GetContainerReference(config["BlobStorageContainerName"])
                .GetBlockBlobReference(filetoDownload);
        }

Нам нужно functionByFileName для обработки каждого элемента из каждого из эти списки.

Но, как вы видите, здесь много повторяющейся информации.

Есть ли способ, которым я могу свести это к одной коллекции и затем иметь возможность манипулировать содержимым коллекции, чтобы избежать всего этого повторения?

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

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