2013-06-27 2 views
0

У меня проблема с использованием перечислений. Предположим, что я определил перечисление, которое имена DeviceType, которые используются внешними клиентами, определяют Устройства, которые они хотят использовать из контейнера Devices. Но поскольку перечисление не расширяется, я не могу иметь новые устройства без обновления моей библиотеки и обновления всех пользователей до новой версии. Я ищу как можно более простое решение этой проблемы. Я не хочу использовать атрибуты или любые другие «читерские» плюсы.Дизайн шаблонов для изменения перечисления?

public class Program 
{ 
    private static List<IDevice> devices; 

    public static void Main(String[] args) 
    { 
     devices = new List<IDevice>() 
     { 
      new NetworkDevice() 
     }; 
     IEnumerable<IDevice> currentDevices = GetDevices(DeviceType.Network); 

     IEnumerable<IDevice> newDevices = GetDevices(DeviceType.NewNetwork); // Will not work, unless client updates my library to get newly added enum types 
    } 

    private static IEnumerable<IDevice> GetDevices(DeviceType type) 
    { 
     return devices.Where(device => device.Type == type); 
    } 
} 

public enum DeviceType 
{ 
    Network 
} 

public interface IDevice 
{ 
    DeviceType Type { get; } 
} 

public class NetworkDevice : IDevice 
{ 
    public DeviceType Type 
    { 
     get 
     { 
      return DeviceType.Network; 
     } 
    } 
} 
+0

??????????????? –

+0

может быть просто использовать 'Словарь' вместо перечисления? –

+3

Звучит так, будто вы говорите: «Я хочу использовать перечисление, но перечисление не может делать то, что я хочу». Я предлагаю не использовать перечисление. – bengoesboom

ответ

2

Использование перечисления для представления типа часто означает, что вы должны создавать классные иерархии.

Аналогичным образом, switching на перечислении, представляющем тип, обычно означает, что существует один или несколько виртуальных методов, которые необходимо ввести где-то в эту иерархию.

Как использовать тип перечисления? Есть ли способ представить свои применения в качестве вызовов виртуальных методов?

(код в вашем вопросе показывает устройства определенного типа фильтруется для, но он не показывает, какие методы вы вызываете для тех пунктов, после того как они были найдены.)

[EDIT] В качестве альтернативой, вы можете пойти на полный ядерный с этим и использовать Managed Extensibility Framework. Этот тип нарушает ваше «отсутствие обмана», хотя ...;)

+0

Я счастлив НЕ использовать перечисления, но я не знаю, как изменить структуру класса, чтобы он мог поддерживать новые устройства, запрашиваемые с клиентского кода. Что касается кода клиентского использования, то просто используйте методы интерфейса IDevice (скажем, «void Init()» и т. Д. », Но он будет использовать конкретную реализацию через наследование. –

+0

@ user2528957 Это действительно звучит так, будто вам нужен« плагин », архитектура, подобная этой управляемой платформе расширяемости: http://msdn.microsoft.com/en-us/library/dd460648.aspx –

+0

ok Я постараюсь в нее копать –

0

Ваш лучший выбор - это List<string> и заполнить его из какого-либо архивного хранилища. При этом вы можете обновить хранилище данных с допустимыми значениями, которые будут использоваться для связанных List<string>.

public enum DeviceType 
{ 
    Network 
} 

больше не нужно будет существовать, и вы бы обновить чтения компакт-дисков, чтобы просто использовать строку

public interface IDevice 
{ 
    string Type { get; } 
} 

@Matthew имеет большую точку. Однако, если ваша основная проблема заключается в том, чтобы изменить значения без перекомпиляции кода, потребуется что-то подобное выше.