Sur une activité custom, la méthode CacheMetadata fait un peu peur car son utilité est difficilement compréhensible au premier abord. Je commencerais donc par éclaircir le sujet avec une petite définition maison :

La méthode CacheMetadata permet à l'activité se décrire elle-même et indique ce qu'elle contient : Variables, Arguments, Activités… etc… quand un workflow ou le designer l'interroge.

Donc on peut déjà noter les points suivants :

  • Nous ne somme pas maîtres des appels faits à cette méthode.
  • La fameuse metadata qui passe au travers de cette méthode n'appartient pas à l'activité, mais au workflow.
  • Les appels à cette méthode peuvent avoir lieu à tout moment durant le design ou l'exécution d'un workflow contenant notre activité.

Par défaut on peut laisser cette méthode de côté et ne pas la réécrire et WF utilisera la réflexion pour peupler la metadata dont il a besoin. Seul ombre au tableau, la réflexion peut être gourmande en ressources et elle ne serra pas en mesure de trouver des éléments privés (ce qui peut être utile pour interdire l'accès à des argument ou variables).

Si on veut de la performance et couvrir chaque cas, il faut donc enregistrer soit même les composants de son activité dans la metadata.

Voici donc quelques exemples de code qui vous permettrons coder proprement vos méthode CacheMetaData :

- L'ajout d'activités :

public Activity MyActivity { get; set; }
public Collection<Activity> MyActivities { get; set; }

protected override void CacheMetadata(NativeActivityMetadata metadata)
{
    // Ajout d'une activité
    metadata.AddChild(this.MyActivity);

    // Ajout de plusieurs activités
    if (this.MyActivities != null
        && this.MyActivities.Count > 0)
    {
        this.MyActivities
            .ToList()
            .ForEach(a => metadata.AddChild(a)); // Merci Linq ;)
    }
}

- L'ajout de variables :

public Variable<String> MyVariable { get; set; }
public Collection<Variable> MyVariables { get; set; }        

protected override void CacheMetadata(NativeActivityMetadata metadata)
{
    // Ajout d'un varaible
    metadata.AddVariable(this.MyVariable);

    // Ajout de plusieurs varaibles
    if (this.MyVariables != null
        && this.MyVariables.Count > 0)
    {
        this.MyVariables
            .ToList()
            .ForEach(v => metadata.AddVariable(v)); // Merci Linq ;)
    }
}

- L'ajout d'arguments (un peu plus difficile): pensez à bien modifier le nom de votre argument si il venait à changer. Le sens (In, Out, InOut) a aussi son importance.

public InArgument<String> MyStringArgument { get; set; }

protected override void CacheMetadata(NativeActivityMetadata metadata)
{
    // Ajout d'un argument
    RuntimeArgument arg = new RuntimeArgument("MyInArgument", typeof(String), ArgumentDirection.In);
    metadata.AddArgument(arg);
    metadata.Bind(this.MyInArgument, arg);
}

- L'ajout d'arguments dont le type est inconnu (la plus tordue je vous l'accorde, mais cela m'est déjà arrivé) :

public InOutArgument MyArgument { get; set; }

protected override void CacheMetadata(NativeActivityMetadata metadata)
{
    // Ajout d'un argument de type inconnu
    Type argType = this.MyStringArgument == null
        ? typeof(Object)
        : this.MyArgument.ArgumentType;

    RuntimeArgument arg = new RuntimeArgument("MyArgument", argType, ArgumentDirection.InOut);
    metadata.AddArgument(arg);
    metadata.Bind(this.MyStringArgument, arg);
}

Note importante : pas de variables, ni d'activités dans les metadatas produites par vos CodeActivities (restons logiques).