VisualBasicValue <t>:访问自定义类及其方法\属性</t>

时间:2011-04-27 10:17:40

标签: c# workflow-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;
    }
}

现在我想使用VisualBasicValue<T>在WF4活动之间移动和处理它的属性。例如:

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();
    }
}

此代码编译没有问题。变量可以处理任何类,但运行时它似乎抱怨自定义类的用法。一些例外,如:

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".

运营商'&amp;'没有为类型'String'和'WorkflowConsoleApplication3.Test'定义。

我读过你可以这样做:

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`?这似乎是我可以在以后使用的东西,但我会找到任何一种例子。

2 个答案:

答案 0 :(得分:1)

我进行了一些更改以使您的代码正常工作。

  1. 变量构造函数是 更改为使用ActivityFunc 过载
  2. 第二个WriteLine需要 在。中显式调用ToString() 表达
  3. 更正后的代码如下

    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();
    }
    

    还有一件事。有些人质疑为什么有必要使用VB Concat运算符显式调用Test.ToString()。这是一个奇怪的问题,它是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 : " & 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
    

    当处理像VB这样的问题时,我经常只创建VB控制台应用程序以测试除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
    

    此应用程序发出的IL显示操作员

    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 :(得分:0)

以下代码有效。请注意我使用lambda而不是固定值初始化变量的方式,第二个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: \" & 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();
}

我必须对Test类进行一些小改动,为字符串连接添加一个+运算符。     公共课测试     {         public string MyString {get;组; }         public bool MyBool {get;组; }

    public override string ToString()
    {
        return "Test Class : " + this.MyString + " - " + MyBool;
    }

    public static string operator +(string s, Test t)
    {
        return s + t.ToString();
    }
}