问题
Suppose I've a custom class (any class), with its methods and properties:
public class Test
{
public string MyString { get; set; }
public bool MyBool { get; set; }
public override string ToString()
{
return "Test Class : " + this.MyString + " - " + MyBool;
}
}
Now I want to move and handle its properties between WF4 activities using VisualBasicValue<T>
. For example:
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: \" & varName.MyString & \"-\" & varName.MyBool") },
new WriteLine() { Text = new VisualBasicValue<string>("\"Test Class ToString(): \" & varName") }
}
};
WorkflowInvoker.Invoke(wf);
Console.ReadKey();
}
}
This code compiles without a problem. Variable can handle any kind of class, but while running it seems to complain of the custom class usage. Some exception like:
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(): " & varName".
Operator '&' is not defined for types 'String' and 'WorkflowConsoleApplication3.Test'.
I've read that you can do something along this lines:
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);
But that doesn't seems to do the trick. Any help?
PS: At the same topic, can someone give me a little example how\where to use VisualBasicReference<T>' with
OutArgument`? It seems something I can use at a later stage but I'm to find any kind of example.
回答1:
I made a couple of changes to make your code work.
- The Variable constructor is changed to use the ActivityFunc overload
- The second WriteLine needs to call ToString() explicitly in the expression
The corrected code is as follows
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: \" & varName.MyString & \"-\" & varName.MyBool")
},
// Changed to call ToString explicitly
new WriteLine { Text = new VisualBasicValue<string>("\"Test Class ToString(): \" & 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();
}
One more thing. Some have questioned why it was necessary to call Test.ToString() explicitly with the VB Concat operator. This is a curious issue and it is one of the places where a type declared in C# differs from a type declared in VB.
C# uses the + operator for both addition and concatenation where VB has the & operator for concat and a specific IL instruction op_Concat.
If you declare your type in VB, you can overload the & operator to eliminate the need to call ToString() in your expression.
For example
Public Class Test
Public Property MyString As String
Public Property MyBool As Boolean
Public Overrides Function ToString() As String
Return "Test Class : " & MyString + " - " & MyBool
End Function
Public Shared Operator &(ByVal left As String, ByVal right As Test) As String
Return left & "-" & right.ToString
End Operator
End Class
When working on problems like in VB I often just create VB console apps to test things out apart from Workflow
Module Module1
Dim varName As New Test With {.MyBool = True, .MyString = "some string"}
Sub Main()
Console.WriteLine("Test Class Properties: " & varName.MyString & "-" & varName.MyBool)
Console.WriteLine("Test Class ToString(): " & varName)
Console.ReadKey()
End Sub
End Module
The IL emitted for this app shows the operator
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)
回答2:
The following code works. Note the way I initialize the variable with a lambda instead of a fixed value and the second VB expression uses a + instead of an &. The last looks like a bug to me and I am going to follow up on that.
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: \" & varName.MyString & \"-\" & 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();
}
I had to make a small change to the Test class to add a + operator for the string concatenation. public class Test { public string MyString { get; set; } public bool MyBool { get; set; }
public override string ToString()
{
return "Test Class : " + this.MyString + " - " + MyBool;
}
public static string operator +(string s, Test t)
{
return s + t.ToString();
}
}
来源:https://stackoverflow.com/questions/5802497/visualbasicvaluet-access-custom-classes-and-its-methods-properties