Partager via


Chaînage avant des règles

Le chaînage est basé sur les dépendances identifiées parmi des règles ; plus spécifiquement, les dépendances parmi les actions d'une règle et les conditions d'autres règles. Ces dépendances peuvent être identifiées ou déclarées à l'aide des trois méthodes suivantes :

  • Implicite

  • Basée sur les attributs

  • Explicite

Implicite

Les dépendances implicites sont identifiées automatiquement par le moteur d'exécution de workflow. Lorsqu'une classe RuleSet est tout d'abord exécutée, chaque règle est analysée pour évaluer les champs/propriétés qu'elle lit dans sa condition et dans lesquels elle écrit dans ses actions. Cela est fait en parcourant l'expression de la condition et les instructions des actions. Par exemple, si les règles sont les suivantes :

Rule 1
IF this.discount > 0
THEN this.total = (1-this.discount) * this.subtotal

Rule 2
IF this.subtotal > 10000
THEN this.discount = 0.05

Le moteur d'exécution de workflow évalue les règles et identifie que la règle 1 lit les champs de remise et de sous-total et écrit dans le champ Total. La règle 2 lit le champ de sous-total et écrit dans le champ de remise ; par conséquent, la règle 1 a une dépendance sur la règle 2. Le résultat est que le moteur d'exécution de workflow s'assure que cette règle 1 est évaluée ou réévaluée toutes les fois que la règle 2 exécute son action Then.

Les dépendances sont identifiées au niveau du nœud feuille, comme dans l'exemple RuleSet suivant.

Rule 1
IF this.order.Discount > 0
THEN this.order.Total = (1-this.order.Discount) * this.order.Subtotal

Rule 2
IF this.order.Subtotal > 10000
THEN this.order.Discount= 0.05

Rule 3 
IF this.order.CustomerType = "Residential"
THEN ...

Une dépendance peut encore être identifiée entre les règles 1 et 2. Toutefois, la règle 3 n'a pas de dépendance sur la règle 1 ni la règle 2 car aucune ne met à jour la propriété CustomerType. En d'autres termes, la dépendance est identifiée au niveau de la propriété CustomerType et non pas au niveau de l'objet Order lui-même.

À l'aide du chaînage implicite, Windows Workflow Foundation effectue la plupart du chaînage nécessaire à la place de l'utilisateur. Par conséquent, l'utilisateur n'a pas à modéliser explicitement les mises à jour et peut, en général, ne pas se préoccuper du chaînage ni de la nécessité de ce dernier. Cela rend la modélisation de rulesets complexes plus simple et en fait une fonction principalement cachée du moteur d'exécution de workflow.

Les deux autres mécanismes entraînant le chaînage, basé sur les attributs et explicite, sont fournis pour des scénarios plus complexes et plus spécifiques.

Basée sur les attributs

Pour les appels de méthode dans une règle, il devient plus difficile d'évaluer de façon déterministe les lectures/écritures qui se produisent. Pour résoudre ce problème, Windows Workflow Foundation fournit trois attributs qui peuvent s'appliquer à une méthode pour indiquer ses actions :

  • RuleRead

  • RuleWrite

  • RuleInvoke

Doter une méthode de l'attribut RuleReadAttribute indique qu'elle lit la propriété indiquée. De la même façon, l'attribut RuleWriteAttribute peut être utilisé pour indiquer qu'une méthode met à jour une propriété ou un champ donné. Supposons que les deux premières règles décrites à la section concernant la méthode implicite ont été réécrites comme suit :

Rule 1
IF this.discount > 0
THEN this.total = (1-this.discount) * this.subtotal

Rule 2
IF this.subtotal > 10000
THEN this.SetDiscount(0.05)

La méthode SetDiscount peut alors être dotée d'attributs comme ci-dessous. Ce qui permet au moteur d'identifier que la règle 1 est dépendante de la règle 2 en raison de l'utilisation du champ de remise.

[RuleWrite("discount")] 
void SetDiscount(double requestedDiscount)
{
...//Some code that updates the discount field.
}

L'attribut RuleInvokeAttribute peut être utilisé pour dicter des dépendances provoquées par des appels de méthode liés. Par exemple, supposons que la modification suivante est appliquée aux règles et aux méthodes :

Rule 1
IF this.discount > 0
THEN this.total = (1-this.discount) * this.subtotal

Rule 2
IF this.subtotal > 10000
THEN this.SetDiscountWrapper(0.05)

[RuleInvoke("SetDiscount")]
void SetDiscountWrapper(double requestedDiscount)
{
     ...
     SetDiscount(requestedDiscount);
     ...
}

[RuleWrite("discount")] 
void SetDiscount(double requestedDiscount)
{
}

L'action de la règle 2 appelle SetDiscountWrapper. Cela appelle à son tour SetDiscount, qui écrit dans le champ de remise. L'attribut RuleInvokeAttribute permet la déclaration de cette écriture indirecte et sa détection par le moteur d'exécution de workflow.

Vous devez être en mesure de reconnaître que le champ ou la propriété référencée dans le chemin d'accès de l'attribut fait référence à un champ ou à une propriété appartenant à la même classe que la méthode. Ce n'est pas nécessairement l'objet racine passé à la classe RuleSet pour l'exécution. Par exemple, vous pouvez associer des attributs à la classe Order comme suit :

public class Order
{
     private double discount;

     public double Discount
     {
         get { return discount;}
         set { discount = value;}
     }

     [RuleWrite("Discount")] 
     void CalculateDiscount(double requestedDiscount, double weighting)
     {
...       //Some code that updates the discount field.
     }
}

Vous pouvez ensuite utiliser une instance de cette classe dans un workflow de la façon suivante :

public class Workflow1 : SequentialWorkflowActivity
{
     private Order discount;
     ...
}

L'exécution de la règle 2 provoque la réévaluation de la règle 1 :

Rule 1
IF this.order.Discount > 5
THEN ...

Rule 2
IF ...
THEN this.order.CalculateDiscount( 5.0, .7)

Utilisation d'attributs

Quelques commentaires supplémentaires sur l'utilisation d'attributs :

  • Les attributs peuvent être utilisés pour spécifier comment sont utilisés les paramètres dans la méthode. Par exemple, la méthode suivante est dotée d'attributs pour indiquer qu'elle modifie la propriété Discount (remise) sur l'instance Order (commande) passée.

    [RuleWrite("currentOrder/Discount", RuleAttributeTarget.Parameter)]
    private void SetDiscount(Order currentOrder, double discount)
    {
        currentOrder.Discount = discount;
    }
    
  • Les caractères génériques peuvent également être utilisés dans les attributs de règle. Par exemple, RuleWrite("order/*") peut être utilisé pour indiquer que tous les champs de l'objet référencés par le champ « order » sont modifiés par la méthode. Toutefois, le caractère générique peut être utilisé uniquement à la fin du chemin d'accès ; un attribut tel que RuleWrite("*/Discount") n'est pas valide.

  • Un attribut tel que RuleWrite("order") peut être utilisé avec les types de référence pour indiquer que la référence a changé ; par exemple, pour indiquer que la variable pointe désormais vers une autre instance Order. Toutes les règles qui utilisent un champ/propriété dans la variable sont supposées être affectées, en plus de toutes les règles qui testent la référence d'instance elle-même ; par exemple, IF this.order == this.order2.

  • Si aucun attribut de méthode n'est spécifié, le comportement par défaut est qu'un appel de méthode est supposé ne pas lire ni écrire de champ/propriété sur l'objet cible (l'objet sur lequel la méthode est appelée). En outre, il est supposé que l'appel de méthode lit des paramètres et les écrit en fonction de mots clés (ref, out, ByVal, ByRef, etc.) définis dans le .NET Framework.

Explicite

Le dernier mécanisme permettant d'indiquer des dépendances de champ/propriété est l'utilisation de l'instruction Update. L'instruction Update utilise comme argument une chaîne qui représente le chemin d'accès à un champ ou à une propriété, ou une expression qui représente l'accès à un champ/propriété. Par exemple, l'une des deux instructions suivantes peut être entrée dans l'outil RuleSet Editor pour créer une instruction Update sur la propriété Name d'une instance Customer sur le workflow.

Update("this/customer/Name") 
OR
Update(this.customer.Name)
NoteRemarque :

Le RuleSet Editor affiche toujours la mise à jour en tant que Update("this/customer/Name").

L'instruction Update indique que la règle écrit dans le champ/propriété indiqué. Cela a le même effet qu'un ensemble direct du champ/propriété dans la règle ou que l'appel d'une méthode à l'aide de RuleWriteAttribute pour le champ/propriété.

L'instruction Update prend également en charge l'utilisation de caractères génériques. Par exemple, vous pouvez ajouter l'instruction Update suivante à une règle :

Update("this/customer/*")

Cela provoque la réévaluation des règles qui utilisent toute propriété sur l'instance Customer dans leurs conditions. En d'autres termes, les deux règles suivantes sont réévaluées :

IF this.customer.ZipCode == 98052
THEN ...

IF this.customer.CreditScore < 600
THEN ...

En général, vous n'avez pas à modéliser d'instructions Update explicites dans la plupart des scénarios ; le chaînage implicite doit fournir l'analyse et le chaînage de dépendance requis. Doter les méthodes d'attributs doit permettre de prendre en charge les scénarios les plus courants où le chaînage implicite ne peut pas identifier les dépendances. En général, l'association d'attributs aux méthodes doit être privilégiée pour indiquer des dépendances par rapport à l'utilisation de l'instruction Update, car la dépendance peut être identifiée une fois sur la méthode et référencée dans de nombreuses règles différentes qui utilisent cette méthode. De plus, dans les scénarios où le writer de règle et l'implémenteur de méthode sont des personnes différentes (ou si le travail est fait à des moments différents), l'association d'attributs aux méthodes permet au writer de méthode (grâce à une meilleure compréhension du code) d'identifier quelles sont les dépendances de la méthode.

Toutefois, il existe quelques scénarios dans lesquels l'instruction Update est la solution appropriée, par exemple lorsqu'un champ/propriété est passé à une méthode sur une classe que vous, en tant que writer de workflow, ne contrôlez pas et par conséquent, sur laquelle vous ne pouvez pas définir d'attributs. Cela est illustré par l'exemple suivant.

IF ...
THEN this.customer.UpdateCreditScore(this.currentCreditScore)
Update(this.currentCreditScore)

Voir aussi

Référence

RuleSet
RuleUpdateAction
RuleHaltAction
RuleWriteAttribute
RuleReadAttribute
RuleReadWriteAttribute
RuleInvokeAttribute

Concepts

Utilisation de RuleSets dans les workflows
Évaluation des règles dans des RuleSets

Footer image

Copyright ©2007 par Microsoft Corporation. Tous droits réservés.