WF e Serializzazione

Una classe normalmente contiene uno o più campi i cui valori determinano lo stato delle sue istanze.
Nel caso in cui la classe in esame fosse una WF Activity occorre fare un po' d'attenzione.

Infatti, durante la vita di una WF Instance può capitare che si debba salvarne lo stato per poterlo recuperare in un secondo momento, anche molto avanti nel tempo e magari su una macchina diversa da quella su cui l'istanza era in esecuzione. Questa operazione, che prende il nome di Passivation, prevede che l'intero WF e le Activity che lo compongono siano serializzabili.

Un'Activity è serializzabile se i suoi campi lo sono, pena il verificarsi di comportamenti poco chiari.
Ad esempio, l'inizializzazione di un'ipotetico campo di tipo MyClass così definito:

public sealed class MyClass { }

all'interno di un'Activity del tipo:

public sealed class MyActivity : Activity
{
    MyClass myClass;
    
    
//...
}

è sufficiente a causare la mancata esecuzione dell'Activity stessa. Infatti, basta inizializzare il campo myClass come segue:

protected override void Initialize(IServiceProvider provider)
{
    
base.Initialize(provider);
    
this.myClass = new MyClass();
}

per fare in modo che il metodo Execute non venga chiamato e saltando invece al metodo Uninitialize.

I rimedi sono due:

  1. rendere serializzabile il tipo MyClass;
  2. se il campo myClass può essere ricostruito al termine della de-serializzazione dell'Activity, lo si può rendere non-serializzabile attraverso l'attributo NonSerialized;
  3. si trasforma il campo myClass in una variabile locale del metodo Execute, istanziandola quindi ad ogni esecuzione dell'Activity; tale pratica prevede che le istanze di MyClass siano veloci da creare, altrimenti si deve ripiegare sui rimedi precedenti.

Spostare una WF Activity da un assembly

Facendo refactoring di una Solution VS 2005, ho deciso di spostare alcune WF Activity da un assembly ad un altro. Il primo assembly era stato creato come Workflow Activity Library, mentre il secondo come semplice Class Library. La sorpresa è arrivata al momento della visualizzazzione in VS dell'Activity portata sul secondo assembly, quando mi sono imbattuto in questo errore:

"The service 'System.Workflow.ComponentModel.Design.IIdentifierCreationService' must be installed for this operation to succeed. Ensure that this service is available."

Dopo una breve indagine ho scoperto che un file di progetto .csproj destinato a contenere Activity e/o Workflow deve assolutamente contenere alcune linee che istruiscano VS a caricare le estensioni per WF. Ovviamente il progetto Class Library non è a conoscenza di queste informazioni, mentre lo è il wizard Workflow Activity Library.

Per sapere come sistemare velocemente le cose si può leggere questo post.