VisualBasicValue <T>: доступ к пользовательским классам и их методам \ свойствам - PullRequest
0 голосов
/ 27 апреля 2011

Предположим, у меня есть собственный класс (любой класс) с его методами и свойствами:

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: \" & 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`? Кажется, что-то, что я могу использовать на более позднем этапе, но я должен найти любой пример.

Ответы [ 2 ]

1 голос
/ 28 апреля 2011

Я сделал пару изменений, чтобы ваш код работал.

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

Еще одна вещь.Некоторые задаются вопросом, почему необходимо было явно вызывать Test.ToString () с оператором VB Concat.Это любопытная проблема, и это одно из мест, где тип, объявленный в 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, чтобы протестировать их отдельно от 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)
0 голосов
/ 27 апреля 2011

Следующий код работает. Обратите внимание, как я инициализирую переменную с помощью лямбды вместо фиксированного значения, а второе выражение 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 {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();
    }
}
...