다음을 통해 공유


C# 식

.NET Framework 4.5부터 C# 식은 Windows WF(Workflow Foundation)에서 지원됩니다. .NET Framework 4.5를 대상으로 하는 Visual Studio 2012에서 만든 새 C# 워크플로 프로젝트는 C# 식을 사용하고 Visual Basic 워크플로 프로젝트는 Visual Basic 식을 사용합니다. Visual Basic 식을 사용하는 기존 .NET Framework 4 워크플로 프로젝트는 프로젝트 언어에 관계없이 .NET Framework 4.6.1로 마이그레이션할 수 있으며 지원됩니다. 이 항목에서는 WF의 C# 식에 대한 개요를 제공합니다.

워크플로에서 C# 식 사용

워크플로 디자이너에서 C# 식 사용

.NET Framework 4.5부터 C# 식은 Windows WF(Workflow Foundation)에서 지원됩니다. .NET Framework 4.5를 대상으로 하는 Visual Studio 2012에서 만든 C# 워크플로 프로젝트는 C# 식을 사용하고 Visual Basic 워크플로 프로젝트는 Visual Basic 식을 사용합니다. 원하는 C# 식을 지정하려면 C# 식 Enter라는 상자에 입력합니다. 이 레이블은 디자이너 또는 워크플로 디자이너의 활동에서 활동을 선택할 때 속성 창에 표시됩니다. 다음 예제에서는 두 개의 WriteLine 활동이 Sequence에 포함되며, 이는 NoPersistScope 안에 위치합니다.

자동으로 생성된 시퀀스 작업을 보여 주는 스크린샷.

비고

C# 식은 Visual Studio에서만 지원되며 다시 호스팅된 워크플로 디자이너에서는 지원되지 않습니다. 다시 호스팅된 디자이너에서 지원되는 새로운 WF45 기능에 대한 자세한 내용은 다시 호스트된 워크플로 디자이너의 새 Workflow Foundation 4.5 기능에 대한 지원을 참조하세요.

이전 버전과의 호환성

.NET Framework 4.6.1로 마이그레이션된 기존 .NET Framework 4 C# 워크플로 프로젝트의 Visual Basic 식이 지원됩니다. Visual Basic 식이 유효한 C# 구문이 아니면 워크플로 디자이너에서 Visual Basic 식을 볼 때 기존 Visual Basic 식의 텍스트 가 XAML에서 설정된 값으로 바뀝니다. Visual Basic 식이 유효한 C# 구문이면 식이 표시됩니다. Visual Basic 식을 C#으로 업데이트하려면 워크플로 디자이너에서 편집하고 해당하는 C# 식을 지정할 수 있습니다. Visual Basic 식을 C#으로 업데이트할 필요는 없지만 워크플로 디자이너에서 식이 업데이트되면 C#으로 변환되고 Visual Basic으로 되돌릴 수 없습니다.

코드 워크플로에서 C# 식 사용

C# 식은 .NET Framework 4.6.1 코드 기반 워크플로에서 지원되지만 워크플로를 호출하기 전에 C# 식을 사용하여 TextExpressionCompiler.Compile컴파일해야 합니다. 워크플로 작성자는 CSharpValue를 식의 r-값을 나타내는 데, 그리고 CSharpReference를 식의 l-값을 나타내는 데 사용할 수 있습니다. 다음 예제에서는 Assign 활동과 WriteLine 활동이 Sequence 활동에 포함된 워크플로가 생성됩니다. A CSharpReference 는 식의 To인수에 Assign 대해 지정되고 식의 l 값을 나타냅니다. CSharpValueValue의 인수와 Assign의 인수에 대해 지정되며, 이 두 식의 r-값을 나타냅니다.

Variable<int> n = new Variable<int>
{
    Name = "n"
};

Activity wf = new Sequence
{
    Variables = { n },
    Activities =
    {
        new Assign<int>
        {
            To = new CSharpReference<int>("n"),
            Value = new CSharpValue<int>("new Random().Next(1, 101)")
        },
        new WriteLine
        {
            Text = new CSharpValue<string>("\"The number is \" + n")
        }
    }
};

CompileExpressions(wf);

WorkflowInvoker.Invoke(wf);

워크플로가 생성되면 도우미 메서드를 호출 CompileExpressions 하여 C# 식이 컴파일된 다음 워크플로가 호출됩니다. 다음 예제는 메서드입니다 CompileExpressions .

static void CompileExpressions(Activity activity)
{
    // activityName is the Namespace.Type of the activity that contains the
    // C# expressions.
    string activityName = activity.GetType().ToString();

    // Split activityName into Namespace and Type.Append _CompiledExpressionRoot to the type name
    // to represent the new type that represents the compiled expressions.
    // Take everything after the last . for the type name.
    string activityType = activityName.Split('.').Last() + "_CompiledExpressionRoot";
    // Take everything before the last . for the namespace.
    string activityNamespace = string.Join(".", activityName.Split('.').Reverse().Skip(1).Reverse());

    // Create a TextExpressionCompilerSettings.
    TextExpressionCompilerSettings settings = new TextExpressionCompilerSettings
    {
        Activity = activity,
        Language = "C#",
        ActivityName = activityType,
        ActivityNamespace = activityNamespace,
        RootNamespace = null,
        GenerateAsPartialClass = false,
        AlwaysGenerateSource = true,
        ForImplementation = false
    };

    // Compile the C# expression.
    TextExpressionCompilerResults results =
        new TextExpressionCompiler(settings).Compile();

    // Any compilation errors are contained in the CompilerMessages.
    if (results.HasErrors)
    {
        throw new Exception("Compilation failed.");
    }

    // Create an instance of the new compiled expression type.
    ICompiledExpressionRoot compiledExpressionRoot =
        Activator.CreateInstance(results.ResultType,
            new object[] { activity }) as ICompiledExpressionRoot;

    // Attach it to the activity.
    CompiledExpressionInvoker.SetCompiledExpressionRoot(
        activity, compiledExpressionRoot);
}

비고

C# 식이 컴파일되지 않은 경우 워크플로가 호출될 때 다음과 유사한 메시지와 함께 예외가 발생합니다: '1'을 실행하려면 컴파일이 필요합니다. 워크플로가 컴파일되었는지 확인하세요.'

사용자 지정 코드 기반 워크플로에서 DynamicActivity를 사용하는 경우, 다음 코드 예제와 같이 CompileExpressions 메서드를 일부 변경해야 합니다.

static void CompileExpressions(DynamicActivity dynamicActivity)
{
    // activityName is the Namespace.Type of the activity that contains the
    // C# expressions. For Dynamic Activities this can be retrieved using the
    // name property , which must be in the form Namespace.Type.
    string activityName = dynamicActivity.Name;

    // Split activityName into Namespace and Type.Append _CompiledExpressionRoot to the type name
    // to represent the new type that represents the compiled expressions.
    // Take everything after the last . for the type name.
    string activityType = activityName.Split('.').Last() + "_CompiledExpressionRoot";
    // Take everything before the last . for the namespace.
    string activityNamespace = string.Join(".", activityName.Split('.').Reverse().Skip(1).Reverse());

    // Create a TextExpressionCompilerSettings.
    TextExpressionCompilerSettings settings = new TextExpressionCompilerSettings
    {
        Activity = dynamicActivity,
        Language = "C#",
        ActivityName = activityType,
        ActivityNamespace = activityNamespace,
        RootNamespace = null,
        GenerateAsPartialClass = false,
        AlwaysGenerateSource = true,
        ForImplementation = true
    };

    // Compile the C# expression.
    TextExpressionCompilerResults results =
        new TextExpressionCompiler(settings).Compile();

    // Any compilation errors are contained in the CompilerMessages.
    if (results.HasErrors)
    {
        throw new Exception("Compilation failed.");
    }

    // Create an instance of the new compiled expression type.
    ICompiledExpressionRoot compiledExpressionRoot =
        Activator.CreateInstance(results.ResultType,
            new object[] { dynamicActivity }) as ICompiledExpressionRoot;

    // Attach it to the activity.
    CompiledExpressionInvoker.SetCompiledExpressionRootForImplementation(
        dynamicActivity, compiledExpressionRoot);
}

동적 작업에서 CompileExpressions C# 식을 컴파일하는 오버로드에는 몇 가지 차이점이 있습니다.

  • CompileExpressions에 대한 매개변수는 DynamicActivity입니다.

  • 형식 이름과 네임스페이스는 DynamicActivity.Name 속성을 사용하여 검색됩니다.

  • TextExpressionCompilerSettings.ForImplementationtrue로 설정됩니다.

  • CompiledExpressionInvoker.SetCompiledExpressionRootForImplementation 가 대신 호출됩니다 CompiledExpressionInvoker.SetCompiledExpressionRoot.

코드에서 식을 사용하는 방법에 대한 자세한 내용은 명령적 코드를 사용하여 워크플로, 활동 및 식 작성을 참조하세요.

XAML 워크플로에서 C# 식 사용

C# 식은 XAML 워크플로에서 지원됩니다. 컴파일된 XAML 워크플로는 형식으로 컴파일되고 느슨한 XAML 워크플로는 런타임에 의해 로드되고 워크플로가 실행될 때 활동 트리로 컴파일됩니다.

컴파일된 Xaml

C# 식은 .NET Framework 4.6.1을 대상으로 하는 C# 워크플로 프로젝트의 일환으로, 형식으로 컴파일되는 XAML 워크플로에서 지원됩니다. 컴파일된 XAML은 Visual Studio에서 워크플로 작성의 기본 형식이며, .NET Framework 4.6.1을 대상으로 하는 Visual Studio에서 만든 C# 워크플로 프로젝트는 C# 식을 사용합니다.

자유로운 Xaml

C# 식은 유연한 XAML 워크플로에서 지원됩니다. 느슨한 XAML 워크플로를 로드하고 호출하는 워크플로 호스트 프로그램은 .NET Framework 4.6.1을 대상으로 해야 하며CompileExpressions(기본값: true)로 설정 false 해야 합니다. CompileExpressionstrue로 설정하려면 ActivityXamlServicesSettings 속성이 CompileExpressions으로 설정된 true 인스턴스를 생성하여 ActivityXamlServices.Load에 매개 변수로 전달하십시오. CompileExpressionstrue으로 설정되지 않으면, 다음과 유사한 메시지와 함께 NotSupportedException가 발생합니다: Expression Activity type 'CSharpValue1'는 실행하려면 컴파일이 필요합니다. 워크플로가 컴파일되었는지 확인하세요.'

ActivityXamlServicesSettings settings = new ActivityXamlServicesSettings
{
    CompileExpressions = true
};

DynamicActivity<int> wf = ActivityXamlServices.Load(new StringReader(serializedAB), settings) as DynamicActivity<int>;

XAML 워크플로 작업에 대한 자세한 내용은 XAML에서 워크플로 및 활동 직렬화를 참조하세요.

XAMLX 워크플로 서비스에서 C# 식 사용

C# 식은 XAMLX 워크플로 서비스에서 지원됩니다. 워크플로 서비스가 IIS 또는 WAS에서 호스트되는 경우 추가 단계가 필요하지 않지만 XAML 워크플로 서비스가 자체 호스팅되는 경우 C# 식을 컴파일해야 합니다. 자체 호스팅 XAMLX 워크플로 서비스에서 C# 식을 컴파일하려면 먼저 XAMLX 파일을 AWorkflowService로 로드한 다음 Body 섹션에서 설명한 메서드에 전달 WorkflowServiceCompileExpressions 합니다. 다음 예제에서는 XAMLX 워크플로 서비스가 로드되고 C# 식이 컴파일된 다음 워크플로 서비스가 열리고 요청을 기다립니다.

// Load the XAMLX workflow service.
WorkflowService workflow1 =
    (WorkflowService)XamlServices.Load(xamlxPath);

// Compile the C# expressions in the workflow by passing the Body to CompileExpressions.
CompileExpressions(workflow1.Body);

// Initialize the WorkflowServiceHost.
var host = new WorkflowServiceHost(workflow1, new Uri("http://localhost:8293/Service1.xamlx"));

// Enable Metadata publishing/
ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
smb.HttpGetEnabled = true;
smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
host.Description.Behaviors.Add(smb);

// Open the WorkflowServiceHost and wait for requests.
host.Open();
Console.WriteLine("Press enter to quit");
Console.ReadLine();

C# 식이 컴파일되지 Open 않으면 작업이 성공하지만 워크플로가 호출될 때 실패합니다. 다음 CompileExpressions 메서드는 코드 워크플로 섹션에서 이전 C# 식 사용의 메서드와 동일합니다 .

static void CompileExpressions(Activity activity)
{
    // activityName is the Namespace.Type of the activity that contains the
    // C# expressions.
    string activityName = activity.GetType().ToString();

    // Split activityName into Namespace and Type.Append _CompiledExpressionRoot to the type name
    // to represent the new type that represents the compiled expressions.
    // Take everything after the last . for the type name.
    string activityType = activityName.Split('.').Last() + "_CompiledExpressionRoot";
    // Take everything before the last . for the namespace.
    string activityNamespace = string.Join(".", activityName.Split('.').Reverse().Skip(1).Reverse());

    // Create a TextExpressionCompilerSettings.
    TextExpressionCompilerSettings settings = new TextExpressionCompilerSettings
    {
        Activity = activity,
        Language = "C#",
        ActivityName = activityType,
        ActivityNamespace = activityNamespace,
        RootNamespace = null,
        GenerateAsPartialClass = false,
        AlwaysGenerateSource = true,
        ForImplementation = false
    };

    // Compile the C# expression.
    TextExpressionCompilerResults results =
        new TextExpressionCompiler(settings).Compile();

    // Any compilation errors are contained in the CompilerMessages.
    if (results.HasErrors)
    {
        throw new Exception("Compilation failed.");
    }

    // Create an instance of the new compiled expression type.
    ICompiledExpressionRoot compiledExpressionRoot =
        Activator.CreateInstance(results.ResultType,
            new object[] { activity }) as ICompiledExpressionRoot;

    // Attach it to the activity.
    CompiledExpressionInvoker.SetCompiledExpressionRoot(
        activity, compiledExpressionRoot);
}