#c# #workflow-foundation-4
#c# #рабочий процесс-foundation-4
Вопрос:
Предположим, у меня есть пользовательский класс (любой класс) со своими методами и свойствами:
public class Test
{
public string MyString { get; set; }
public bool MyBool { get; set; }
public override string ToString()
{
return "Test Class : " this.MyString " - " MyBool;
}
}
Теперь я хочу перемещать и обрабатывать его свойства между действиями WF4 с помощью VisualBasicValue<T>
. Например:
public class Program
{
static void Main(string[] args)
{
Test testClass = new Test()
{
MyString = "some string",
MyBool = true
};
Sequence wf = new Sequence()
{
Variables =
{
new Variable<Test>("varName", testClass),
},
Activities =
{
new WriteLine() { Text = new VisualBasicValue<string>(""Test Class Properties: " amp; varName.MyString amp; "-" amp; varName.MyBool") },
new WriteLine() { Text = new VisualBasicValue<string>(""Test Class ToString(): " amp; varName") }
}
};
WorkflowInvoker.Invoke(wf);
Console.ReadKey();
}
}
Этот код компилируется без проблем. Переменная может обрабатывать любой класс, но во время выполнения она, похоже, жалуется на использование пользовательского класса. Некоторое исключение, подобное:
The following errors were encountered while processing the workflow tree:
'Literal<Test>': Literal only supports value types and the immutable type System.String. The type WorkflowConsoleApplication3.Test cannot be used as a literal.
'VisualBasicValue<String>': Compiler error(s) encountered processing expression ""Test Class ToString(): " amp; varName".
Оператор ‘amp;’ не определен для типов ‘String’ и ‘workflowconsoleapplication 3.Тест’.
Я читал, что вы можете сделать что-то в этом роде:
VisualBasicSettings vbSettings = new VisualBasicSettings();
vbSettings.ImportReferences.Add(new VisualBasicImportReference()
{
Assembly = typeof(Test).Assembly.GetName().Name,
Import = typeof(Test).Namespace
});
// construct workflow
VisualBasic.SetSettings(wf, vbSettings);
WorkflowInvoker.Invoke(wf);
Но, похоже, это не помогает. Любая помощь?
PS: В той же теме, может кто-нибудь привести мне небольшой пример, как где использовать VisualBasicReference<T>' with
OutArgument`? Кажется, это то, что я могу использовать на более позднем этапе, но я должен найти какой-либо пример.
Ответ №1:
Я внес пару изменений, чтобы заставить ваш код работать.
- Конструктор переменных изменен, чтобы использовать перегрузку ActivityFunc
- Вторая строка записи должна явно вызывать toString() в выражении
Исправленный код выглядит следующим образом
private static void Main(string[] args)
{
var testClass = new Test { MyString = "some string", MyBool = true };
var wf = new Sequence
{
Variables = {
// Changed to use ActivityFunc so testClass is not interpreted as a literal
new Variable<Test>("varName", ctx => testClass),
},
Activities =
{
new WriteLine
{
Text =
new VisualBasicValue<string>(
""Test Class Properties: " amp; varName.MyString amp; "-" amp; varName.MyBool")
},
// Changed to call ToString explicitly
new WriteLine { Text = new VisualBasicValue<string>(""Test Class ToString(): " amp; varName.ToString()") }
}
};
var settings = new VisualBasicSettings();
settings.ImportReferences.Add(
new VisualBasicImportReference
{
Assembly = typeof(Test).Assembly.GetName().Name, Import = typeof(Test).Namespace
});
// construct workflow
VisualBasic.SetSettings(wf, settings);
WorkflowInvoker.Invoke(wf);
Console.ReadKey();
}
Еще одна вещь. Некоторые задавались вопросом, зачем было вызывать Test.toString() явно с помощью оператора Concat VB. Это любопытная проблема, и это одно из мест, где тип, объявленный в C #, отличается от типа, объявленного в VB.
C # использует оператор как для сложения, так и для конкатенации, где VB имеет оператор amp; для concat и конкретную инструкцию IL op_Concat.
Если вы объявляете свой тип в VB, вы можете перегрузить оператор amp;, чтобы исключить необходимость вызова toString() в вашем выражении.
Например
Public Class Test
Public Property MyString As String
Public Property MyBool As Boolean
Public Overrides Function ToString() As String
Return "Test Class : " amp; MyString " - " amp; MyBool
End Function
Public Shared Operator amp;(ByVal left As String, ByVal right As Test) As String
Return left amp; "-" amp; right.ToString
End Operator
End Class
При работе над проблемами, подобными VB, я часто просто создаю консольные приложения VB, чтобы протестировать что-то помимо рабочего процесса
Module Module1
Dim varName As New Test With {.MyBool = True, .MyString = "some string"}
Sub Main()
Console.WriteLine("Test Class Properties: " amp; varName.MyString amp; "-" amp; varName.MyBool)
Console.WriteLine("Test Class ToString(): " amp; varName)
Console.ReadKey()
End Sub
End Module
Идентификатор, выданный для этого приложения, показывает оператора
IL_002f: ldstr "Test Class ToString(): "
IL_0034: ldsfld class VBTest.Test VBTest.Module1::varName
IL_0039: call string VBTest.Test::op_Concatenate(string, class VBTest.Test)
IL_003e: call void [mscorlib]System.Console::WriteLine(string)
Комментарии:
1. Да! В этом-то и проблема. Спасибо.
Ответ №2:
Работает следующий код. Обратите внимание на то, как я инициализирую переменную с помощью лямбды вместо фиксированного значения, а второе выражение VB использует вместо amp;. Последнее для меня выглядит как ошибка, и я собираюсь проследить за этим.
static void Main()
{
Test testClass = new Test()
{
MyString = "some string",
MyBool = true
};
Sequence wf = new Sequence()
{
Variables =
{
new Variable<Test>("varName", c => testClass),
},
Activities =
{
new WriteLine() { Text = new VisualBasicValue<string>(""Test Class Properties: " amp; varName.MyString amp; "-" amp; varName.MyBool") },
new WriteLine() { Text = new VisualBasicValue<string>(""Test Class ToString(): " varName") }
}
};
var vbSettings = new VisualBasicSettings();
vbSettings.ImportReferences.Add(new VisualBasicImportReference()
{
Assembly = typeof(Test).Assembly.GetName().Name,
Import = typeof(Test).Namespace
});
VisualBasic.SetSettings(wf, vbSettings);
WorkflowInvoker.Invoke(wf);
Console.ReadKey();
}
Мне пришлось внести небольшое изменение в тестовый класс, чтобы добавить оператор для конкатенации строк.
тест открытого класса
{
общедоступная строка myString { получить; установить; }
общедоступный bool MyBool { получить; установить; }
public override string ToString()
{
return "Test Class : " this.MyString " - " MyBool;
}
public static string operator (string s, Test t)
{
return s t.ToString();
}
}
Комментарии:
1. Я уже исправил эту ошибку вскоре после публикации вопроса, но проблема остается. Это странно, но, похоже, это правильное использование. Знаете ли вы что-нибудь о
VisualBasicSettings
иVisualBasicImportReference
. Держу пари, что в этом проблема.2. Они говорят об этом здесь
3. Какие сообщения об ошибках вы получаете и какое текущее выражение VB вы используете?
4. Сообщения об ошибках приведены в сообщении вопроса выше. В основном это жалобы на то, что тестовый класс не может использоваться как литерал . Я использую точно такие же выражения, как у вас, я обновил ими исходный пост.