Как высушить этот код

Я интегрируюсь с Quickbooks Desktop, используя их SDK. Я хочу создать общий список элементов. Их общий запрос элемента верхнего уровня возвращает все элементы (как тип IORItemRet), а затем имеет различные подтипы элементов в элементе верхнего уровня. Эти подтипы не наследуются от базового класса Item, поэтому мне приходится просматривать каждый возвращаемый элемент, использовать оператор switch для определения его типа, а затем сопоставлять свойства этого конкретного типа с моим общим классом QuickbooksItem.

Как вы можете видеть ниже, код довольно избыточен. Я хотел бы иметь возможность инкапсулировать общие настройки типов свойств ListID и Name, если это вообще возможно.

Любые идеи, чтобы высушить этот код? Я думаю, как минимум, я мог бы создать функцию, которая принимает (ref qbItem, string ListId, string Name) и вызывать ее в каждом case... но это все еще довольно сыро... Я надеялся на что-то более сухое.

public static QuickbooksItem ConvertQueryResponseToClass(IORItemRet itemRet)
{
    var itemType = itemRet.ortype;
    var typeTest = itemRet.Type;

    QuickbooksItem qbItem = new QuickbooksItem();

    switch (itemType)
    {
        case ENORItemRet.orirItemServiceRet:
            var itemService = itemRet.ItemServiceRet as IItemServiceRet;
            qbItem.Id = itemService.ListID.GetValue();
            qbItem.Name = itemService.Name.GetValue();
            qbItem.ItemType = ItemTypes.Service;
            break;

        case ENORItemRet.orirItemInventoryRet:
            var itemInventory = itemRet.ItemInventoryRet as IItemInventoryRet;
            qbItem.Id = itemInventory.ListID.GetValue();
            qbItem.Name = itemInventory.Name.GetValue();
            qbItem.ItemType = ItemTypes.Inventory;
            break;

        case ENORItemRet.orirItemNonInventoryRet:
            var itemNonInventory = itemRet.ItemNonInventoryRet as IItemNonInventoryRet;
            qbItem.Id = itemNonInventory.ListID.GetValue();
            qbItem.Name = itemNonInventory.Name.GetValue();
            qbItem.ItemType = ItemTypes.NonInventory;
            break;

        case ENORItemRet.orirItemOtherChargeRet:
            var itemOtherCharge = itemRet.ItemOtherChargeRet as IItemOtherChargeRet;
            qbItem.Id = itemOtherCharge.ListID.GetValue();
            qbItem.Name = itemOtherCharge.Name.GetValue();
            qbItem.ItemType = ItemTypes.Other;
            break;

        case ENORItemRet.orirItemSalesTaxRet:
            var itemSalesTax = itemRet.ItemSalesTaxRet as IItemSalesTaxRet;
            qbItem.Id = itemSalesTax.ListID.GetValue();
            qbItem.Name = itemSalesTax.Name.GetValue();
            qbItem.ItemType = ItemTypes.SalesTax;
            break;

        case ENORItemRet.orirItemSalesTaxGroupRet:
            var itemSalesTaxGroup = itemRet.ItemSalesTaxGroupRet as IItemSalesTaxGroupRet;
            qbItem.Id = itemSalesTaxGroup.ListID.GetValue();
            qbItem.Name = itemSalesTaxGroup.Name.GetValue();
            qbItem.ItemType = ItemTypes.SalesTaxGroup;
            break;
    }

    return qbItem;
}

person crichavin    schedule 16.02.2016    source источник
comment
Вы возможно сможете что-то сделать с Reflection для свойств, одинаковых для всех типов.   -  person Dave    schedule 16.02.2016
comment
stackoverflow .com/questions/5379730/   -  person Dave    schedule 16.02.2016
comment
Итак, все эти типы объявляют и реализуют члены одного и того же типа с одним и тем же именем (ListID, Name), но все они делают это без использования общего базового класса?   -  person Amit    schedule 16.02.2016
comment
Звучит как что-то, что QuickBooks сделает.   -  person Dave    schedule 16.02.2016
comment
Некоторая комбинация шаблонов адаптера и фасада позволит вам ввести интерфейс для представления свойств, общих для каждого из интерфейсов QB, но в этом случае я не уверен, что это действительно даст вам что-то, кроме дополнительного кода.   -  person tomRedox    schedule 16.02.2016
comment
Это кажется довольно открытым и может лучше подходить для codereview.stackexchange.com.   -  person Sam Hanley    schedule 16.02.2016
comment
Веселый вызов! Проголосовал за, потому что я люблю высушивать свой код. Я думаю...   -  person Casey Crookston    schedule 16.02.2016
comment
@Амит, это правильно.   -  person crichavin    schedule 16.02.2016
comment
@CaseyCrookston, то, что вам нравится данный вид деятельности, не означает, что это обязательно хороший вопрос для переполнения стека. Открытые вопросы проверки кода явно не относятся к теме SO - ожидается, что вопросы будут, по крайней мере, в некоторой степени, касаться конкретного вопроса, на который можно дать окончательный ответ. Пожалуйста, не голосуйте за вопросы не по теме.   -  person Sam Hanley    schedule 17.02.2016


Ответы (2)


У меня нет способа проверить это, но что-то вроде этого должно работать:

var itemType = itemRet.ortype;
var typeTest = itemRet.Type;

QuickbooksItem qbItem = new QuickbooksItem();

PropertyInfo ListIdProperty = typeTest.GetProperty("ListID");
MethodInfo ListValueMethod = ListIdProperty.GetMethod("GetValue");

qbItem.Id = (int)ListValueMethod.Invoke(ListIdProperty.GetValue(itemRet, null), null);
person Dave    schedule 16.02.2016

Одна из идей состоит в том, чтобы использовать библиотеку типа AutoMapper для сопоставления каждого типа с вашим классом QuickbooksItem.

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

person Fábio Junqueira    schedule 16.02.2016
comment
Я люблю Automapper, но если он не изменился недавно, ему нужно будет вручную создать сопоставление для каждого типа, так что это все равно не будет очень СУХИМ. - person Dave; 16.02.2016
comment
Верно, но я считаю, что размещение сопоставлений в файле конфигурации делает код чище. - person Fábio Junqueira; 17.02.2016
comment
Вы можете создать карту, и если имена свойств совпадают, она автоматически сопоставит их без необходимости указывать их по отдельности. - person Matthew Steeples; 22.02.2016