устранение дублирующегося Перечислимого кода

В моей среде код не работал в этом URL http://motzcod.es/post/94643411707/enhancing-xamarinforms-listview-with-grouping .

Код, который не работает, здесь

var partnersSorted = from item in Partners
         orderby item.UserName
         group item by item.UserNameSort into PartnersGroup
         select new Grouping(PartnersGroup.Key, PartnersGroup);

MonkeysGrouped = new ObservableCollection>(partnersSorted);

Итак, я изменил код.

var sortedPartners = Partners.OrderBy(x => x.UserName).GroupBy(y => y.UserNameSort);
foreach (var item in sortedPartners)
{
     PartnersGrouped.Add(new PartnersGrouping(item.Key, Partners.Where(x=>x.UserNameSort == item.Key)));
}

Вы можете видеть вот так.

[ https://i.stack.imgur.com/BswPq.png] [1]

вот мои все скрипты

Элемент является партнером

Item.cs

using System;

namespace NewHeats.Models
{
    public class Item
    {
        public string Id
        {
            get;
            set;
        }
        public string UserName
        {
            get;
            set;
        }
        public DateTime RegisterDate
        {
            get;
            set;
        }
        public string Field
        {
            get;
            set;
        }
        public string Password
        {
            get;
            set;
        }
        public int Heats
        {
            get;
            set;
        }
        public string UserNameSort
        {
             get
            {
                 if (string.IsNullOrWhiteSpace(UserName) || UserName.Length == 0)
                    return "?";

                 return UserName[0].ToString().ToUpper();
            }
        }
    }
 }

PartnersGrouping.cs

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
namespace NewHeats.Models
{
    public class PartnersGrouping : ObservableCollection
    {
        public K Key { get; private set; }

        public PartnersGrouping(K key,IEnumerable items)
        {
            Key = key;
            foreach (var item in items)
            {
                this.Items.Add(item);
            }
        }
    }
}

PartnersViewModel.cs

using System;
using System.Windows.Input;
using System.ComponentModel;
using System.Collections.ObjectModel;
using Xamarin.Forms;
using NewHeats.Models;
using System.Threading.Tasks;
using System.Diagnostics;
using System.Linq;
using System.Diagnostics.Contracts;

namespace NewHeats.ViewModels
{
    public class PartnersViewModel : BaseViewModel
    {
        public Item Me
        {
            get;
            set;
        }
        public ObservableCollection Partners { get; set; }
        public ObservableCollection> PartnersGrouped { get; set; }
        public Item SelectedPartner { get; set; }
        public Command LoadPartnersCommand { get; set; }
        public PartnersViewModel()
        {
            Title = "Partners";
            Partners = new ObservableCollection();
            PartnersGrouped = new ObservableCollection>();
            LoadPartnersCommand = new Command(async() =>await ExecuteLoadPartnersCommand());
        }

        async Task ExecuteLoadPartnersCommand()
        {
            Contract.Ensures(Contract.Result() != null);
            if (IsBusy)
                return;
            IsBusy = true;
            try
            {
                Me = await MockUsrDataStore.GetItemAsync("naoto");                           
                Partners.Clear();
                var allfriends = await MockFriDataStore.GetItemsAsync(true);                 
                var myFriends = allfriends.Where(x => x.MyId == Me.Id);                      
                var allUsers = await MockUsrDataStore.GetItemsAsync(true);                   

                foreach (var item in myFriends)
                {
                    var partner = allUsers.FirstOrDefault(x => x.Id == item.FriendId);       
                    if (partner!=null)
                    {
                        Partners.Add(partner);
                    }
                }
                var sortedpartners = Partners.OrderBy(x => x.UserName).GroupBy(y => y.UserNameSort);
                foreach (var item in sortedpartners)
                {
                     PartnersGrouped.Add(new PartnersGrouping(item.Key, Partners.Where(x=>x.UserNameSort == item.Key)));
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex);
            }
            finally
            {
                IsBusy = false;
            }
        }
    }
}

PartnerPage.xaml



    
        
            
            #2196F3
            #96d1ff
            #999999
        
    
    
        
            
        
        
            
                
                    
                        
                            
                                
                                       
                            
                        
                    
                    
                        
                            
                                
                                    
                                        
                                    
                                    
                                        
                                        
                                    
                                    
                                    
                                       
                                           
                                
                            
                        
                    
                
            
        
    

Спасибо !!

22
задан Dónal 17 September 2008 в 04:00
поделиться

14 ответов

Вы могли включить дублированный код в CodeableEnumHelper класс:

public class CodeableEnumHelper {
    public static CodeableEnum getByCode(String code, CodeableEnum[] values) {
        for (CodeableEnum e : values) {
            if (e.getCode().equalsIgnoreCase(code)) {
                return e;
            }
        }
        return null;
    }
}

Каждый CodeableEnum класс должен был бы все еще реализовать getByCode метод, но фактическая реализация метода была, по крайней мере, централизована к единственному месту.

public enum IMType implements CodeableEnum {
    ...
    public IMType getByCode(String code) {
        return (IMType)CodeableEnumHelper.getByCode(code, this.values());
    } 
}
13
ответ дан varzeak 29 November 2019 в 05:19
поделиться

В Вашем конкретном случае getCode () / getByCode (Код строки) методы кажется очень закрытым (эвфемистически говорящий) к поведению toString () / valueOf (Строковое значение) методы, предоставленные всем перечислением. Почему Вы не хотите использовать их?

0
ответ дан Nicolas 29 November 2019 в 05:19
поделиться

Почти настолько близко, как я добрался до того, что Вы хотите, должен был создать шаблон в IntelliJ, который 'реализует' универсальный код (использующий valueOf перечисления (Имя строки)). Не прекрасный, но работает вполне хорошо.

0
ответ дан Javamann 29 November 2019 в 05:19
поделиться

Если Вы действительно хотите наследование, не забывайте, что Вы можете реализовывать перечислимый шаблон сами , как в плохие старые дни Java 1.4.

0
ответ дан Mwanji Ezana 29 November 2019 в 05:19
поделиться

Как насчет статического общего метода? Вы могли снова использовать его из getByCode своего перечисления () методы или просто использовать его непосредственно. Я всегда пользовательские целочисленные идентификаторы для моих перечислений, таким образом, мой getById () метод только имеет, действительно делаю это: возвращаемые значения () [идентификатор]. Это намного быстрее и более просто.

0
ответ дан 29 November 2019 в 05:19
поделиться

Я не думаю, что это возможно. Однако Вы могли использовать valueOf перечисления (Имя строки) метод, если бы Вы собирались использовать имя перечисления значений в качестве своего кода.

0
ответ дан Jorn 29 November 2019 в 05:19
поделиться

Создайте безопасный с точки зрения типов служебный класс, который загрузит перечисления кодом:

интерфейс сводится:

public interface CodeableEnum {
    String getCode();
}

служебный класс:

import java.lang.reflect.InvocationTargetException;


public class CodeableEnumUtils {
    @SuppressWarnings("unchecked")
    public static <T extends CodeableEnum>  T getByCode(String code, Class<T> enumClass) throws IllegalArgumentException, SecurityException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
        T[] allValues = (T[]) enumClass.getMethod("values", new Class[0]).invoke(null, new Object[0]);
        for (T value : allValues) {
            if (value.getCode().equals(code)) {
                return value;
            }
        }
        return null;
}

}

использование демонстрации тестового сценария А:

import junit.framework.TestCase;


public class CodeableEnumUtilsTest extends TestCase {
    public void testWorks() throws Exception {
    assertEquals(A.ONE, CodeableEnumUtils.getByCode("one", A.class));
      assertEquals(null, CodeableEnumUtils.getByCode("blah", A.class));
    }

enum A implements CodeableEnum {
    ONE("one"), TWO("two"), THREE("three");

    private String code;

    private A(String code) {
        this.code = code;
    }

    public String getCode() {
        return code;
    }   
}
}

Теперь Вы только копируете getCode () метод и getByCode (), метод находится в одном месте. Могло бы быть хорошо обернуть все исключения в единственный RuntimeException также:)

1
ответ дан triggerNZ 29 November 2019 в 05:19
поделиться

К сожалению, я не думаю, что существует способ сделать это. Ваш лучший выбор был бы про успешно, чтобы должным быть сдаться в перечислениях в целом и использовать стандартный класс дополнительные и статические участники. Иначе привыкните к дублированию того кода. Извините.

1
ответ дан Daniel Spiewak 29 November 2019 в 05:19
поделиться

У меня была подобная проблема с компонентом локализации, который я записал. Мой компонент разработан для доступа к локализованным сообщениям с перечислимыми константами что индекс в пакет ресурса, не тяжелая проблема.

я нашел, что копировал и вставлял тот же "шаблонный" код перечисления повсеместно. Моим решением избежать дублирования является генератор кода, который принимает конфигурационный XML-файл с перечислимыми постоянными именами и конструктором args. Вывод является исходным кодом Java с "дублированными" поведениями.

Теперь, я поддерживаю конфигурационные файлы и генератор, не весь дублированный код. Везде у меня был бы перечислимый исходный код, существует теперь файл конфигурации XML. Мои сценарии сборки обнаруживают устаревшие сгенерированные файлы и вызывают генератор кода для создания перечислимого кода.

Вы видите этот компонент здесь . Шаблон, который я копировал и вставлял, факторизуется в таблица стилей XSLT . генератор кода выполнения преобразование таблицы стилей. входной файл довольно краток по сравнению со сгенерированным перечислимым исходным кодом.

HTH,
Greg

2
ответ дан Greg Mattes 29 November 2019 в 05:19
поделиться

Абстрактные перечисления потенциально очень полезны (и в настоящее время не позволенные). Но предложение и прототип существуют, если требуется лоббировать кого-то в Sun для добавления его:

http://freddy33.blogspot.com/2007/11/abstract-enum-ricky-carlson-way.html

RFE Sun:

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6570766

7
ответ дан Alex Miller 29 November 2019 в 05:19
поделиться

Убрать код dave:

public class CodeableEnumHelper {
    public static <E extends CodeableEnum> E getByCode(
        String code, E[] values
    ) {
        for (E e : values) {
            if (e.getCode().equalsIgnoreCase(code)) {
                return e;
            }
        }
        return null;
    }
}

public enum IMType implements CodableEnum {
    ...
    public IMType getByCode(String code) {
        return CodeableEnumHelper.getByCode(code, values());
    } 
}

Или более эффективно:

public class CodeableEnumHelper {
    public static <E extends CodeableEnum> Map<String,E> mapByCode(
        E[] values
    ) {
        Map<String,E> map = new HashMap<String,E>();
        for (E e : values) {
            map.put(e.getCode().toLowerCase(Locale.ROOT), value) {
        }
        return map;
    }
}

public enum IMType implements CodableEnum {
    ...
    private static final Map<String,IMType> byCode =
        CodeableEnumHelper.mapByCode(values());
    public IMType getByCode(String code) {
        return byCode.get(code.toLowerCase(Locale.ROOT));
    } 
}
5
ответ дан Tom Hawtin - tackline 29 November 2019 в 05:19
поделиться

Кажется на фактическую реализацию информации о типе выполнения. Java обеспечивает это как функцию языка.

я предлагаю, чтобы Вы искали RTTI или отражение.

0
ответ дан Dave Hillier 29 November 2019 в 05:19
поделиться

Другим решением было бы не помещать ничего в само перечисление, а просто предоставить двунаправленную карту Enum <-> Code для каждого перечисления. Вы могли бы, например, используйте для этого ImmutableBiMap из Google Collections.

Таким образом, никакого дублирования кода не будет.

Пример:

public enum MYENUM{
  VAL1,VAL2,VAL3;
}

/** Map MYENUM to its ID */
public static final ImmutableBiMap<MYENUM, Integer> MYENUM_TO_ID = 
new ImmutableBiMap.Builder<MYENUM, Integer>().
put(MYENUM.VAL1, 1).
put(MYENUM.VAL2, 2).
put(MYENUM.VAL3, 3).
build();
0
ответ дан 29 November 2019 в 05:19
поделиться

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

Вы создаете интерфейс, который реализует ваше перечисление:

public interface EnumWithId {

    public int getId();

}

Затем во вспомогательном классе вы просто создаете метод, подобный этому:

public <T extends EnumWithId> T getById(Class<T> enumClass, int id) {
    T[] values = enumClass.getEnumConstants();
    if (values != null) {
        for (T enumConst : values) {
            if (enumConst.getId() == id) {
                return enumConst;
            }
        }
    }

    return null;
}

Затем этот метод можно использовать следующим образом:

MyUtil.getInstance().getById(MyEnum.class, myEnumId);
0
ответ дан 29 November 2019 в 05:19
поделиться
Другие вопросы по тегам:

Похожие вопросы: