2014-09-15 4 views
0

Я хочу построить что-то вроде конвейера, где я могу поместить команды (преобразователи, считыватели, писатели ...) вместе, как линейный рабочий процесс и соединить их по заданным параметрам команд. Все должно быть сериализуемым, а чистый xml - обязательным, , потому что графический редактор не планируется на первом этапе, поэтому xml редактируется (с созданной схемой и поддержкой intellisense в VS это не боль).Конфигурируемые/динамические параметры

Пример:

<DataCommand name="AboFileReader"> 
<connection> 
    <parameter name="filename" direction="in" type="string"> 
    <parameter name="tabledata" direction="out" type="DataTable"> 
</connection>  
</DataCommand> 
<DataCommand name="TrimConverter"> 
<connection> 
    <param name="tabledata" direction="in" type="DataTable" > 
    <param name="tabledata" direction="out" type="DataTable" > 
</connection> 
</DataCommand>  
<DataCommand name="AboDataConverter"> 
<connection> 
    <param name="tabledata" direction="in" type="DataTable" > 
    <param name="tabledata" direction="out" type="DataTable" > 
</connection> 
</DataCommand> 
<DataCommand name="AboSqlWriter"> 
<connection> 
    <param name="tabledata" direction="in" type="DataTable" > 
</connection> 
</DataCommand> 

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

Сначала я подумал, что 1. путь, но затем я придумал решение 3. потому что он дает чистый xml и является родным сериализуемым. Для следующего шага (редактора) привязка к GUI должна быть легкой, а propertygrid, делающий отражение, не является моим первым выбором (отражение всегда уродливо), наличие набора параметров может быть легко привязано к графическому интерфейсу.

Возможно, комбинация 1 и 3 - путь, чтобы собрать все параметры в коллекции при запуске?

1. Данные-аннотаций

[Parameter(Direction = "In", Description="...")] 
public string FileName {get; set;} 

[Parameter(Direction = "Out", Description="...")] 
public DataTable Table {get; set;} 

Плюсы: + родные параметры подвергаются + IntelliSense при кодировании

Минусы: - родной сериализации? - уродливый xml?

2. Workflow Foundation в стиле Windows

public InParameter<string> FileName {get; set;} 

public OutParameter<DataTable> Table {get; set;} 

Плюсы: + IntelliSense при кодировании + параметры подвергаются + сериализации работает

Минусы: - уродливый XML?

3. Сбор заполнила в конструкторе

ObservableCollection<Parameter> Parameters {get; set;} 

public Init() 
{ 
    Parameters.Add(new Parameter() { Name="FileName", Type = typeOf(string), Direction="In", Description="..." }); 
    Parameters.Add(new Parameter() { Name="Table", Type = typeOf(DataTable), Direction="Out", Description="..." }); 
} 

Pros: + сериализация работает + чистый XML

Минусы: - параметры не отображаются в исходный код - не IntelliSense при кодировании

Каков ваш опыт и каков путь?

+1

Это интересный вопрос. Он кажется немного шире, как он в настоящее время спросил, и может быть лучше подходит для такого сайта, как http://codereview.stackexchange.com/ – xDaevax

ответ

0

Лично я выбрал бы менее многословный представление XML, что-то вроде:

<ReadFile filename="..." /> 
<Trim /> 
<Convert /> 
<WriteSQL /> 

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

  1. виден в структуре коды - это не служит в качестве документации, и позволяет ваша IDE поможет вам
  2. легко сериализовать - не repetetive, подверженные ошибкам коды
  3. легко читаются в последовательной форме - так что вы хотите чистого XML

вы хотите использовать свойство из-за номер 1. из числа 2, вы хотите, чтобы автоматически определить, какие свойства нужно чтобы быть сериализованным - вот где возникает отражение. Из-за номера 3 вы захотите сериализуйте только те поля, которые настраиваются, поэтому вам нужно что-то отличить от этих свойств.

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

Вот как я бы создать основы:

public interface IOperation 
{ 
    Type InputType { get; } 
    Type OutputType { get; } 

    object GetOutput(object input); 
} 

Каждая операция обеспечивает свою собственную реализацию интерфейса IOperation:

public class ReadFileOperation : IOperation 
{ 
    [Parameter] 
    public string Filename { get; set; } 

    public Type InputType { get { return null; } } // No input 
    public Type OutputType { get { return typeof(DataTable); } } 

    public object GetOutput(object input) 
    { 
     // TODO: Read file into DataTable here! 
    } 
} 

Если у вас есть операции, которые могут быть сконфигурированы для работы с различные типы ввода или вывода, а затем давая InputType или OutputType сеттер и атрибут [Parameter] должен работать нормально.

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

public Dictionary<Type, List<PropertyInfo>> DetectParameterProperties() 
{ 
    Dictionary<Type, List<PropertyInfo>> lookup = new Dictionary<Type, List<PropertyInfo>>(); 

    IEnumerable<Type> operations = Assembly 
     .GetAssembly(typeof(IOperation)) 
     .GetTypes() 
     .Where(t => t.IsClass && !t.IsAbstract && typeof(IOperation).IsAssignableFrom(t)); 

    foreach (Type operation in operations) 
    { 
     lookup[operation] = new List<PropertyInfo>(); 

     IEnumerable<PropertyInfo> parameters = operation.GetProperties().Where(p => p.CustomAttributes.Any(a => a.AttributeType == typeof(ParameterAttribute))); 
     foreach (PropertyInfo parameter in parameters) 
      lookup[operation].Add(parameter); 
    } 

    return lookup; 
} 

Обратите внимание, что при предоставлении дополнительных параметров конфигурации обработка ошибок становится более важной. Простая проверка типов для обеспечения соответствия всех типов ввода и вывода хороша, но для некоторых операций могут потребоваться собственные проверки, чтобы они не были неправильно настроены каким-либо другим способом.

+0

Здравствуйте, спасибо за ваше предложение, как я понимаю, вы правы, вы строите смесь из 1. и 2.? Xml не должен быть подробным (но я имею в виду, что типы и разные пространства имен не должны появляться), но ваши кажутся мне немного пощадить. Должен сказать, что возможны несколько параметров ввода/вывода (извините, в моем примере я их не использовал). Я хочу вернуть список , например. когда мои данные будут проверены на раздвоение, я пробовал получать два типа данных (например, «ValidAbos» и «InvalidAbos»). – JohnnyBravo75

+0

Нет, это в значительной степени ваш подход 1, а не 2. Различные выходы немного меняют ситуацию ... вы выбираете один из выходов и игнорируете другие (-ы), или вы хотите обрабатывать все выходы (в этом случае , это уже не линейный процесс, а ветвящийся)? –

+0

Ветвление не нужно. Я думаю, и это сделало бы все это сложным и полным рабочим процессом. Например, недействительные abos могут быть записаны в файл в самом валидаторе и не должны обрабатываться дальше, но только наличие параметра может быть немного ограничено. когда у вас есть параметры multipe, я должен их назвать.У меня есть вопрос относительно вашего решения, почему вы отметили имя файла как [Параметр], но не вернули строку в качестве InputType? В чем преимущество вашего решения? Насколько я понимаю, по сравнению с 1 сериализации будет работать и по сравнению с 2, вид ввода/вывода видны? – JohnnyBravo75

Смежные вопросы