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

При написании пользовательских действий для повторно размещенного конструктора рабочих процессов я получаю сообщение об ошибке, что для обязательного аргумента требуется значение, если у меня его нет, поэтому я либо использую нуль, как показано ниже, либо «ВСЕ». Он не принимает null или «ALL» или что-либо еще в качестве аргумента по умолчанию. Обратите внимание, что мой обязательный аргумент имеет тип строки.

[RequiredArgument]
[DefaultValue(null)]
[Description(@"The status of the job to perform")]
public InArgument<string> JobStatus { get; set; }

[RequiredArgument]
[DefaultValue("All")]
[Description(@"The status of the job to perform")]
public InArgument<string> JobStatus { get; set; }

Сообщение об ошибке при запуске рабочего процесса:

Консоль рабочего процесса: запуск рабочего процесса...

Не удалось запустить рабочий процесс.

Сообщение: Не удалось запустить рабочий процесс DynamicActivity.

Сообщение об исключении: при обработке дерева рабочего процесса были обнаружены следующие ошибки: «DynamicActivity»: частная реализация действия «1: DynamicActivity» имеет следующую ошибку проверки: значение для требуемого аргумента действия «JobStatus» не было предоставлено.

Трассировка стека: в System.Activities.Validation.ActivityValidationServices.ThrowIfViolationsExist(IList`1 validationErrors) в System.Activities.Hosting.WorkflowInstance.ValidateWorkflow(WorkflowInstanceExtensionManager extensionManager) в System.Activities.Hosting.WorkflowInstance.RegisterExtensionManager(WorkflowInstanceExtensionManager extensionManager) в System. Activity.WorkflowApplication.EnsureInitialized() в System.Activities.WorkflowApplication.Enqueue (операция InstanceOperation, логическое значение push) в System.Activities.WorkflowApplication.WaitForTurn (операция InstanceOperation, время ожидания TimeSpan) в System.Activities.WorkflowApplication.InternalRun (время ожидания TimeSpan, логическое значение isUserRun) в System.Activities.WorkflowApplication.Run()

Спасибо за вашу помощь


person user1298925    schedule 20.01.2014    source источник
comment
Итак, вы говорите, что если вы не используете DefaultValue, вы получаете ошибку компиляции?   -  person Mike Perrenoud    schedule 20.01.2014
comment
Нет, я не получаю ошибку компиляции. Когда я запускаю программу, рабочий процесс не запускается. Я опубликую сообщение об ошибке через минуту.   -  person user1298925    schedule 20.01.2014
comment
Почему вы выполняете рабочий процесс без предварительной проверки? И разве разработчик рабочего процесса не предупреждает вас, что для этих InArguments требуется значение?   -  person Joao    schedule 21.01.2014
comment
Я не писал исходный код, я должен проверить, есть ли способ сначала вызвать валидацию или может быть так, что валидация вызывается. Кстати, при запуске рабочего процесса я получаю именно эту ошибку. Отсутствует значение обязательного аргумента (перефразирование)   -  person user1298925    schedule 21.01.2014
comment
Проверьте ActivityValidationServices.Validate.   -  person Joao    schedule 22.01.2014


Ответы (1)


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

В любом случае, вы можете либо инициализировать переменную со значением по умолчанию. Например, в конструкторе:

public class MyCodeActivity : CodeActivity
{
    public MyCodeActivity()
    {
        JobStatus = "All";
    }
}

или форсировать значение через аксессор. Что-то вроде этого:

private InArgument<string> text = "All";

[RequiredArgument]
public InArgument<string> Text
{
    get { return text ?? "All"; }
    set { text = value; }
}

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

protected override void Execute(CodeActivityContext context)
{
    string text = context.GetValue(this.Text);
    if (text == null) 
    {
        text = "All";
    }

    Console.WriteLine(text);
}
person Joao    schedule 21.01.2014
comment
Другой способ сделать это — реализовать IActivityTemplateFactory, как в этом примере. - person ; 21.01.2014
comment
Абсолютно. К сожалению, и это, очевидно, личное мнение, IActivityTemplateFactory является злом и имеет тенденцию скрывать большинство проблем вместо того, чтобы решать их. Помимо возможности превратить дизайн в полный кошмар. - person Joao; 21.01.2014
comment
Спасибо. Итак, какова цель DefaultValue? - person user1298925; 21.01.2014
comment
Более того, атрибут не предназначен для этого. Возможно, я преувеличил, говоря это таким образом. На самом деле DefaultValueAttribute можно использовать для всего, что захочет разработчик. Это просто метаданные, которые вы можете получить и использовать когда угодно (и где угодно). Наиболее распространенные варианты использования связаны с (де)сериализацией, когда метаданные используются в случае пропуска значения. На самом деле этот атрибут используется большинством дизайнеров Visual Studio (WPF, WinForms и т. д.). К сожалению, дизайнер WF не использует его. Дополнительная информация. - person Joao; 22.01.2014
comment
@Jota: не могли бы вы взглянуть на два других моих вопроса об ошибках рабочего процесса в повторно размещенном конструкторе рабочих процессов, пожалуйста? Спасибо. - person user1298925; 23.01.2014