다음을 통해 공유


활동 대리자 사용

작업 대리자를 사용하면 활동 작성자는 활동 사용자가 활동 기반 처리기를 제공할 수 있는 특정 시그니처가 있는 콜백을 노출할 수 있습니다. 두 가지 형식의 작업 대리자를 사용할 수 있습니다. ActivityAction<T>은 반환 값이 없는 작업 대리자를 정의하는 데 사용되고 ActivityFunc<TResult>은 반환 값이 있는 작업 대리자를 정의하는 데 사용됩니다.

작업 대리자는 자식 작업이 특정 서명을 갖도록 제한되어야 하는 시나리오에서 유용합니다. 예를 들어 While 활동은 제약 조건 없이 모든 형식의 자식 활동을 포함할 수 있지만 ForEach<T> 활동의 본문은 ActivityAction<T>이며 최종적으로 ForEach<T>에서 실행되는 자식 활동에는 InArgument<T>이 열거하는 컬렉션 멤버와 동일한 형식의 ForEach<T>이 있어야 합니다.

ActivityAction 사용

Catch 활동이나 ForEach<T> 활동 같은 여러 가지 .NET Framework 4.6.1 활동에 활동 동작이 사용됩니다. 각 경우에 활동 동작은 해당 활동 중 하나를 사용하여 워크플로를 작성할 때 필요한 동작을 제공하기 위해 워크플로 작성자가 활동을 지정하는 위치를 나타냅니다. 다음 예제에서는 ForEach<T> 활동을 사용하여 콘솔 창에 텍스트를 표시합니다. ForEach<T>의 본문은 문자열인 ActivityAction<T>의 형식에 일치하는 ForEach<T>을 사용하여 지정됩니다. WriteLine에 지정된 Handler 활동의 Text 인수는 ForEach<T> 활동의 반복 대상인 컬렉션의 문자열 값에 바인딩됩니다.

DelegateInArgument<string> actionArgument = new DelegateInArgument<string>();

Activity wf = new ForEach<string>
{
    Body = new ActivityAction<string>
    {
        Argument = actionArgument,
        Handler = new WriteLine
        {
            Text = new InArgument<string>(actionArgument)
        }
    }
};

List<string> items = new List<string>();
items.Add("Hello");
items.Add("World.");

Dictionary<string, object> inputs = new Dictionary<string, object>();
inputs.Add("Values", items);

WorkflowInvoker.Invoke(wf, inputs);

actionArgument는 컬렉션의 개별 항목을 WriteLine으로 이동하는 데 사용됩니다. 워크플로가 호출되면 다음 출력이 콘솔에 표시됩니다.

HelloWorld.

이 항목의 예에서는 개체 초기화 구문을 사용합니다. 개체 초기화 구문은 워크플로에 있는 활동의 계층적 뷰를 제공하고 활동 간의 관계를 표시하기 때문에 코드에서 워크플로 정의를 만드는 유용한 방법일 수 있습니다. 프로그래밍 방식으로 워크플로를 만들 때 개체 초기화 구문을 사용하기 위한 요구 사항은 없습니다. 다음 예는 이전 예와 기능적으로 동일합니다.

DelegateInArgument<string> actionArgument = new DelegateInArgument<string>();

WriteLine output = new WriteLine();
output.Text = new InArgument<string>(actionArgument);

ActivityAction<string> body = new ActivityAction<string>();
body.Argument = actionArgument;
body.Handler = output;

ForEach<string> wf = new ForEach<string>();
wf.Body = body;

List<string> items = new List<string>();
items.Add("Hello");
items.Add("World.");

Dictionary<string, object> inputs = new Dictionary<string, object>();
inputs.Add("Values", items);

WorkflowInvoker.Invoke(wf, inputs);

개체 이니셜라이저에 대한 자세한 내용은 방법: 생성자를 호출하지 않고 개체 초기화(C# 프로그래밍 가이드)방법: 개체 이니셜라이저를 사용하여 개체 선언(Visual Basic)을 참조하세요.

다음 예제에서는 TryCatch 활동이 워크플로에 사용됩니다. ApplicationException이 워크플로를 통해 throw되고 Catch<TException> 활동을 통해 처리됩니다. Catch<TException> 활동의 활동 동작에 대한 처리기는 WriteLine 활동이며, 예외 세부 사항은 ex DelegateInArgument<T>를 사용하여 처리기로 전달됩니다.

DelegateInArgument<ApplicationException> ex = new DelegateInArgument<ApplicationException>()
{
    Name = "ex"
};

Activity wf = new TryCatch
{
    Try = new Throw()
    {
        Exception = new InArgument<Exception>((env) => new ApplicationException("An ApplicationException was thrown."))
    },
    Catches =
    {
        new Catch<ApplicationException>
        {
            Action = new ActivityAction<ApplicationException>
            {
                Argument = ex,
                Handler = new WriteLine()
                {
                    Text = new InArgument<string>((env) => ex.Get(env).Message)
                }
            }
        }
    },
    Finally = new WriteLine()
    {
        Text = "Executing in Finally."
    }
};

ActivityAction<T>을 정의하는 사용자 지정 활동을 만들 때는 InvokeAction<T>을 사용하여 해당 ActivityAction<T>의 호출을 모델링합니다. 이 예제에서는 사용자 지정 WriteLineWithNotification 활동을 정의합니다. 이 활동은 Sequence 활동과, 문자열 인수 하나를 사용하는 WriteLine을 호출하는 InvokeAction<T>을 차례로 포함하는 ActivityAction<T>로 구성됩니다.

public class WriteLineWithNotification : Activity
{
    public InArgument<string> Text { get; set; }
    public ActivityAction<string> TextProcessedAction { get; set; }

    public WriteLineWithNotification()
    {
        this.Implementation = () => new Sequence
        {
            Activities =
            {
                new WriteLine
                {
                    Text = new InArgument<string>((env) => Text.Get(env))
                },
                new InvokeAction<string>
                {
                    Action = TextProcessedAction,
                    Argument = new InArgument<string>((env) => Text.Get(env))
                }
            }
        };
    }
}

WriteLineWithNotification 활동을 사용하여 워크플로를 만드는 경우 워크플로 작성자는 필요한 사용자 지정 논리를 활동 동작의 Handler에 지정합니다. 이 예제에서는 WriteLineWithNotification 활동을 사용하는 워크플로를 만들고 WriteLine 활동을 Handler로 사용합니다.

// Create and invoke the workflow without specifying any activity action
// for TextProcessed.
Activity wf = new WriteLineWithNotification
{
    Text = "Hello World."
};

WorkflowInvoker.Invoke(wf);

// Output:
// Hello World.

// Create and Invoke the workflow with specifying an activity action
// for TextProcessed.
DelegateInArgument<string> msg = new DelegateInArgument<string>();
Activity wf2 = new WriteLineWithNotification
{
    Text = "Hello World with activity action.",
    TextProcessedAction = new ActivityAction<string>
    {
        Argument = msg,
        Handler = new WriteLine
        {
            Text = new InArgument<string>((env) => "Handler of: " + msg.Get(env))
        }
    }
};

// Invoke the workflow with an activity action specified
WorkflowInvoker.Invoke(wf2);

// Output:
// Hello World with activity action.
// Handler of: Hello World with activity action.

하나 이상의 인수를 전달하기 위해 제공된 일반 버전의 여러 InvokeAction<T>ActivityAction<T>이 있습니다.

ActivityFunc 사용

ActivityAction<T>은 활동의 결과 값이 없는 경우에 유용하고, 결과 값이 반환되는 경우에는 ActivityFunc<TResult>이 사용됩니다. ActivityFunc<TResult>을 정의하는 사용자 지정 활동을 만들 때는 InvokeFunc<TResult>을 사용하여 해당 ActivityFunc<TResult>의 호출을 모델링합니다. 다음 예제에서는 WriteFillerText 활동을 정의합니다. 필터 텍스트를 제공하기 위해 정수 인수를 사용하고 문자열 결과를 반환하는 InvokeFunc<TResult>을 지정합니다. 필터 텍스트가 검색되면 WriteLine 활동을 사용하여 해당 텍스트가 콘솔에 표시됩니다.

public class WriteFillerText : Activity
{
    public ActivityFunc<int, string> GetText { get; set; }
    public InArgument<int> Quantity { get; set; }

    Variable<string> text = new Variable<string>
    {
        Name = "Text"
    };

    public WriteFillerText()
    {
        this.Implementation = () => new Sequence
        {
            Variables =
            {
                text
            },
            Activities =
            {
                new InvokeFunc<int, string>
                {
                    Func = GetText,
                    Argument = new InArgument<int>((env) => Quantity.Get(env)),
                    Result = new OutArgument<string>(text)
                },
                new WriteLine
                {
                    Text = new InArgument<string>(text)
                }
            }
        };
    }
}

텍스트를 제공하기 위해 int 인수 하나를 사용하고 문자열 결과가 있는 활동을 사용해야 합니다. 이 예제에서는 이 요구 사항과 일치하는 TextGenerator 활동을 보여 줍니다.

public class TextGenerator : CodeActivity<string>
{
    public InArgument<int> Quantity { get; set; }
    public InArgument<string> Text { get; set; }

    protected override string Execute(CodeActivityContext context)
    {
        // Provide a quantity of Random Text
        int q = Quantity.Get(context);
        if (q < 1)
        {
            q = 1;
        }

        string text = Text.Get(context) + " ";
        StringBuilder sb = new StringBuilder(text.Length * q);
        for (int i = 0; i < q; i++)
        {
            sb.Append(text);
        }

        return sb.ToString();
    }
}

TextGenerator 활동을 WriteFillerText 활동과 함께 사용하려면 이 활동을 Handler로 지정합니다.

DelegateInArgument<int> actionArgument = new DelegateInArgument<int>();

Activity wf = new WriteFillerText
{
    Quantity = 5,
    GetText = new ActivityFunc<int, string>
    {
        Argument = actionArgument,
        Handler = new TextGenerator
        {
            Quantity = new InArgument<int>(actionArgument),
            Text = "Hello World."
        }
    }
};

WorkflowInvoker.Invoke(wf);