VisualBasicValue:访问自定义类及其方法属性

本文关键字:方法 属性 自定义 访问 VisualBasicValue | 更新日期: 2023-09-27 17:53:04

假设我有一个自定义类(任何类),以及它的方法和属性:

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

操作符'&'没有为'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 ' ?这似乎是我可以在以后的阶段使用,但我要找到任何类型的例子。

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

我做了一些改变使你的代码工作。

  1. 变量构造函数是改为使用activityfunction过载
  2. 第二个WriteLine需要方法显式调用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: '" & 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使用&用于concat和特定IL指令的操作符op_Concat.

如果你在VB中声明你的类型,你可以重载&操作符,以消除在表达式中调用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控制台应用程序来测试除了工作流之外的东西

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)

下面的代码可以工作。请注意,我用lambda而不是固定值初始化变量的方式,第二个VB表达式使用+而不是&。最后一个对我来说像是一个bug,我将继续跟进。

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类做一个小改动,为字符串连接添加一个+操作符。公开班级测验{公共字符串MyString {get;设置;}公共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();
    }
}