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

发布于 2024-11-03 14:02:24 字数 2199 浏览 4 评论 0原文

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

public class Test
{
    public string MyString { get; set; }
    public bool MyBool { get; set; }

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

现在我想使用 VisualBasicValue 在 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'与OutArgument`?这似乎是我可以在稍后阶段使用的东西,但我会找到任何类型的例子。

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>' withOutArgument`? It seems something I can use at a later stage but I'm to find any kind of example.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

执妄 2024-11-10 14:02:24

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

  1. 变量构造函数是
    更改为使用 ActivityFunc
    重载
  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)

I made a couple of changes to make your code work.

  1. The Variable constructor is
    changed to use the ActivityFunc
    overload
  2. 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)
一念一轮回 2024-11-10 14:02:24

以下代码有效。请注意我使用 lambda 而不是固定值初始化变量的方式,并且第二个 VB 表达式使用 + 而不是 &。最后一个对我来说看起来像是一个错误,我将对此进行跟进。

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 { 获取;放; }
公共 bool MyBool { 获取;放; }

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

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

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();
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文