2010-06-29 5 views
10

Мне интересно, можно ли что-то сделать. У меня есть функция, которая читает xml-файл и добавляет элементы управления в форму, основанную на содержимом файла. Узел XML, как это будет создавать его:Могу ли я иметь тип «класс» в C#?

<Button Top="300" Left="100">Automatic</Button> 

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

  switch (xmlchild.Name) 
      { 
       // Create a new control whose type is specified. 
       case "Button": 
        c = new Button(); 
        break; 
       case "Label": 
        c = new Label(); 
        break; 
       default: 
        c = null; 
        break; 
      } 

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

Спасибо!

+0

Вы можете, например, вызвать свои классы «MyXml *», где * - Button, Label и т. Д., И использовать отражение. – simendsjo

+0

Если вы используете WPF, вы можете использовать классы XamlReader/Writer –

ответ

2

Если вы контролируете содержимое XML-файла, тогда да. Вы можете использовать:

string fullNameSpace = "System.Windows.Controls."; 
Type controlType = Type.GetType(fullNameSpace + xmlchild.Name); 
if(controlType != null) 
{ 
    // get default constructor... 
    ConstructorInfo ctor = controlType.GetConstructor(Type.EmptyTypes); 
    object control = ctor.Invoke(null); 
} 

Вы можете также использовать Activator класс, чтобы очистить это немного:

object control = Activator.CreateInstance("System.Windows.Presentation", 
              xmlchild.Name); 

В качестве альтернативы, если вы можете создать действительный файл XAML, можно использовать XamlReader для восстановления управление деревом.

+0

+1: Спасибо, что преподал мне о Type.EmptyTypes (а также хороший ответ, но может только один раз) –

+0

+1 Даже при том, что код выше будет работать, один проблема заключается в том, что имя типа должно быть правильным, поэтому разработчик не сможет/не сможет уйти от проверки имени элемента управления. В конце будет метод проверки ошибок с аналогичным коммутатором или if/else. –

+0

@Paul - или хороший большой 'try ... catch (Exception)' ... ОК, возможно, более мелкий с более конкретным типом исключения, но вы НЕ ДОЛЖНЫ проверять его раньше времени. –

1

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

Activator.CreateInstance(xmlchild.Name, ...) 

Просто заполните нужные биты, и многое из этого кода уйдет.

1

Похоже, вы ищете нечто вроде Generics.

Вы могли бы сделать что-то следующим образом:

public static class ControlFactory 
{ 
    public static T CreateControl<T>() where T : Type, new() 
    { 
     return new T(); 
    } 
} 

Я не проверял этот код еще, так что я буду обновлять его, как я проверить.

1

См., В первую очередь, класс Activator. Затем вы можете сохранить имя типа элемента управления как атрибут в файле xml и использовать класс Activator для создания экземпляров на основе значения, хранящегося в атрибуте из текущего элемента xml (type = "fullTypeName").

Далее, если речь идет о свойствах, вы можете рассмотреть отражение, чтобы установить свойства в созданных экземплярах на основе имени атрибута (т. Е. У вас есть экземпляр элемента управления, созданного с классом Activator, и вы назначаете vale из Top атрибут в xml для свойства Top созданного экземпляра, который вы можете получить/установить с помощью отражения).

1

Возможно использование Reflection, как описано другими, для конструирования элемента управления непосредственно из его имени. Однако этот дизайн довольно хрупкий и может также представлять проблемы безопасности, если XML-файл является общедоступным, поскольку произвольные типы управления могут быть созданы во время выполнения на основе текста в файле. Это может не беспокоить ваше приложение.

Я бы предпочел дизайн, используя Dictionary<string, Func<Control>>, где у вас есть код, который регистрирует обратный вызов, который создает элемент управления для каждого имени.Это дает вам дополнительную гибкость (вы можете динамически менять методы построения управления или комбинировать доступные элементы управления из нескольких источников), а также может выглядеть более чистым (коммутатор заменяется несколькими «регистрационными» вызовами, а фактическая конструкция разбивается на отдельные методы или (в простом случае) в виде лямбда-выражения). Это также обеспечивает обратную совместимость, если вы замените TextBox в своем приложении MyImprovedTextBox и хотите, чтобы предыдущие файлы конфигурации использовали улучшенную версию.