Vis à vis d’un workflow ou d’une activité décrite en Xaml, l’implémentation en mode impératif (C# ou Vb) n’a que très peu d’avantages… mais elle en a tout de même. Jusqu’ici je n’ai trouvé que deux arguments en faveur du code :

  1. La maitrise du type de base  : Activity<TResult> est utilisable en lieu et place du seul Activity pour Xaml.
  2. L’exposition sous forme d’arguments de propretés, pas ou peu accessible via Xaml.

Pour décrire le premier cas, voici un exemple concret impossible a reproduire en Xaml :

public class CompositeActivityT : Activity<String>
{
    // Délégué de l'implémentation
    private readonly Func<Activity> m_Implementation;

    /// <summary>
    /// Constructeur
    /// </summary>
    public CompositeActivityT()
    {
        this.m_Implementation = new Func<Activity>(this.GetImplementation);
    }

    /// <summary>
    /// Code impératide de l'implémentation
    /// </summary>
    /// <returns></returns>
    private Activity GetImplementation()
    {
        return new Sequence
        {
            Activities = {
                new Assign 
                {
                    To = new OutArgument<String>(c=> this.Result.Get(c)),
                    Value = new InArgument<String>(c=> DateTime.Now.ToString())
                }
            }
        };
    }

    /// <summary>
    /// Implémentation
    /// </summary>
    protected override Func<Activity> Implementation
    {
        get { return this.m_Implementation; }
        set { }
    }
}

En Xaml notre activité de base est obligatoirement Activity, il est dont impossible d’implémenter un tel workflow et donc de récupérer sons argument de sortie aussi facilement qu’avec cette activité ci

Exemple :

String result = WorkflowInvoker.Invoke(new CompositeActivityT());

En une seule ligne, c’est tout de même plus simple  que de passer par un dictionnaire ;)

 

Pour le second cas, on peut prendre l’exemple de l’activité Receive qui a une propriété OperationName de type String qu’il est impossible de binder sur un argument car elle n’accepte pas les expressions :(

public sealed class ServiceSequence : Activity
{
    // Délégué de l'implémentation
    private readonly Func<Activity> m_Implementation;

    private const String c_DefaultMethodeName = "MyMethode";

    private Receive m_Receive;
    private Sequence m_Body;

    [RequiredArgument]
    public String MethodeName
    {
        get
        {
            return this.m_Receive.OperationName;
        }
        set
        {
            this.m_Receive.OperationName = value;
        }
    }

    /// <summary>
    /// Activités contenues dans la séquence
    /// </summary>
    public Collection<Activity> Activities
    {
        get
        {
            return this.m_Body.Activities;
        }
    }

    public ServiceSequence()
    {
        this.m_Implementation = new Func<Activity>(this.GetImplementation);
    }

    /// <summary>
    /// Code impératide de l'implémentation
    /// </summary>
    /// <returns></returns>
    private Activity GetImplementation()
    {
        // handle de correlation
        Variable<CorrelationHandle> handle = new Variable<CorrelationHandle>("handle");

        // Activité Receive dont on pourat changer le nom de la méthode exposée via WCF
        m_Receive = new Receive()
                    {
                        OperationName = c_DefaultMethodeName,
                        ServiceContractName = "IService",
                        CanCreateInstance = true,
                        CorrelationInitializers = 
                        {
                            new RequestReplyCorrelationInitializer() 
                            {
                                CorrelationHandle = handle
                            }
                        }
                    };

        this.m_Body = new Sequence();

        return new Sequence()
            {
                Variables =
                {
                    handle
                },
                Activities = {
                    // Méthode WCF
                    this.m_Receive,

                    // Sequence d'activités
                    this.m_Body,

                    // Réponse WCF
                    new SendReply()
                    {
                        // Association au Receive
                        Request = m_Receive,
                            
                        // Reponse au client WCF (un message contenant une propriété Result de Type boolean retournant vrai)
                        Content = new SendParametersContent()
                        {
                            Parameters = 
                            {
                                new KeyValuePair<String,InArgument>("Result",new InArgument<Boolean>(true))
                            }
                        }
                    }
                }
            };
    }

    /// <summary>
    /// Implémentation
    /// </summary>
    protected override Func<Activity> Implementation
    {
        get { return this.m_Implementation; }
        set { }
    }
}

Typiquement le code de psychopathe qui ne pourrait pas être écrit dans une activité Xaml.

Ah écrire cela peut sembler barbare, mais avec un peu d’entrainement on s’y habitue ;)

Et vous : avez vous trouvez d’autres avantages à la déclaration Vb ou C# des activités composites?