DoomerDGR8
DoomerDGR8

Reputation: 5042

Execute an AsyncCodeActivity from within an AsyncCodeActivity

I'm stuck at a point where I'm suppose to write an activity that encapsulates another pre existing activity.

The pre-existing Activity is call SaySpeech and it has some parameters. The required ones are a Connection and a Text (which it'll speak using TTS on to the connection). Its an AsyncCodeActivity.

I'm making a new activity called SayPassword and it accepts the same parameters as SaySpeech but instead of TextToSpeak, It has PasswordToSpeak. The prelude to this was: Generate a sentence from a pre defined words

Now, before calling SaySpeech internally, I need to provide it with the same parameters as SayPassword received, and replace the TextToSpeak param value with generated PasswordToSpeak.

All is done except that I can't figure out how I'd start the SaySpeech activity in code internally? I need to invoke SaySpeech's BeginExecute within SayPassword's and EndExecute with SayPassword's EndExecute.

Any pointers?

Upvotes: 1

Views: 805

Answers (2)

DoomerDGR8
DoomerDGR8

Reputation: 5042

Ok. After six hours of trials and testing, i finally got my activity running. Here is the final code:

public sealed class SayPassword : NativeActivity
{

    [RequiredArgument]
    public InArgument<ConnectionInfo> Connection { get; set; }
    [RequiredArgument]
    public InArgument<String> Password { get; set; }

    public InArgument<String> Language { get; set; }
    public InArgument<Int32?> Speaker { get; set; }

    #region Implementation
    private SaySpeech InnerSaySpeech { get; set; }

    private Variable<ConnectionInfo> TempConnectionInfo { get; set; }
    private Variable<String> TempUtterance { get; set; }
    private Variable<String[]> TempParameters { get; set; }
    private Variable<String> TempLanguage { get; set; }
    private Variable<Int32?> TempSpeaker { get; set; }
    #endregion

    public SayPassword()
    {
        TempConnectionInfo = new Variable<ConnectionInfo>();
        TempUtterance = new Variable<String>();
        TempParameters = new Variable<String[]>();
        TempLanguage = new Variable<String>();
        TempSpeaker = new Variable<Int32?>();

        InnerSaySpeech = new SaySpeech
        {
            Connection = new InArgument<ConnectionInfo>(TempConnectionInfo),
            Utterance = new InArgument<string>(TempUtterance),
            Parameters = new InArgument<string[]>(TempParameters),
            Language = new InArgument<string>(TempLanguage),
            Speaker = new InArgument<int?>(TempSpeaker)
        };
    }

    private String[] GetSentences(String password) {}

    private static string GetPlaceholderString(Int32 NumberOfPlaceholders) {}

    protected override void CacheMetadata(NativeActivityMetadata metadata)
    {
        base.CacheMetadata(metadata);

        metadata.AddImplementationVariable(TempConnectionInfo);
        metadata.AddImplementationVariable(TempUtterance);
        metadata.AddImplementationVariable(TempParameters);
        metadata.AddImplementationVariable(TempLanguage);
        metadata.AddImplementationVariable(TempSpeaker);

        metadata.AddImplementationChild(InnerSaySpeech);
    }

    protected override void Execute(NativeActivityContext context)
    {
        String[] SpeakablePassword = GetSentences(Password.Get(context));

        context.SetValue(TempConnectionInfo, Connection.Get(context));
        context.SetValue(TempUtterance, GetPlaceholderString(SpeakablePassword.Length));
        context.SetValue(TempParameters, SpeakablePassword);
        context.SetValue(TempLanguage, Language.Get(context));
        context.SetValue(TempSpeaker, Speaker.Get(context));

        context.ScheduleActivity(InnerSaySpeech);
    }
}

I needed to create middle variable for mapping the incoming arguments so that they could be passed on to the inner activity successfully.

The article Misadventures in CacheMetadata – wrapping an inner activity, in code helped me a lot. It seems that the workflow framework is not your everyday c# code. i have a lot to learn still. hope this comes in handy for someone else.

Upvotes: 1

Maurice
Maurice

Reputation: 27632

A CodeActivity doesn't let you execute child acivities, you need to use a NativeActivity instead. In the Execute() method you can use the context.ScheduleActivity() to ask the runtime to execute another activity for you.

public sealed class MyActivity : NativeActivity
{
    public Activity Body { get; set; }

    protected override void Execute(NativeActivityContext context)
    {
        context.ScheduleActivity(Body);
    }
}

Upvotes: 3

Related Questions