2010-07-06 7 views
3

J'ai une classe assez générique (Record) à laquelle j'ai ajouté un gestionnaire de callback, donc je peux faire quelque chose comme ceci.C#: passer des paramètres aux callbacks

record.Save(AfterSaveMethod); 

Qui renvoie également le numéro d'identité de l'enregistrement créé. Le problème que j'ai maintenant est que j'ai cette routine de sauvegarde imbriquée dans une boucle, et j'ai besoin d'utiliser/passer la variable i!

for (int i; i < count ;i++) 
{ 
    record.Save(AfterSaveMethod2) //but I need to pass i through as well 
} 

Que dois-je faire ici?

A \ récrire la méthode de sauvegarde et l'inclure dans cette classe (beurk),

B \ ont une surcharge option d'enregistrement qui prend un objet en tant que paramètre, donc je peux passer à travers à ma classe d'enregistrement, puis fusionnez-le avec le numéro d'identité. En retournant à la fois le numéro d'identité et tout élément supplémentaire contenu dans l'objet transmis (hmm, cela semble un peu brouillon),

C \ existe-t-il une option plus sexy?

Répondre

7

C'est là des méthodes anonymes ou des expressions lambda sont très pratique :)

Essayez ceci (en supposant C# 3):

for (int i = 0; i < count; i++) 
{ 
    int index = i; 
    record.Save(id => AfterSaveMethod2(id, index)); 
} 

Notez que l'expression lambda ici capture index, non i - c'est pour éviter les problèmes inhérents à closing over the loop variable.

+0

Une solution très élégante, M. Skeet! – decyclone

+0

ok, logique, juste besoin de trier le foo;) L'action est mon type de délégué –

+0

@Grayson: Alors, quel est le nombre entier qu'il est passé? –

0
class SexierSaveMethod 
    { 
     public Int32 Index { get; set; } 

     public SexierSaveMethod(Int32 i) 
     { 
      Index = i; 
     } 

     public void AfterSaveMethod() 
     { 
      // Use i here 
     } 
    } 

    record.Save(new SexierSaveMethod(i).AfterSaveMethod); 
2

Vous pouvez aussi créer un (thread-statique) objet de contexte, qui stocke votre « état » (dans ce cas, l'indice de valeur variable), que vous pouvez accéder à l'aide d'une propriété statique (par exemple MyContext.Current). Dépend de la complexité du contexte ...

WCF utilise quelque chose comme ceci avec OperationContext.Current, ASP.NET, TransactionScope et al.

Si le contexte est un peu plus complexe que le vôtre et que vous ne voulez pas polluer les signatures de plusieurs méthodes, je pense que ce modèle est assez soigné.

Utilisation:

// init context 
MyContext.Current = new MyContext(); 
for (var idx = 0; idx < 99; idx++) { 
    MyContext.Current.Idx = idx; 
    record.Save(AfterSaveMethod);   

} 
// uninitialize context 
MyContext.Current = null; 

(échantillon très simpliste)

Si le contexte est [ThreadStatic] vous pourriez avoir plusieurs appels simultanés qui n'affecteront pas les uns des autres

+0

funky, cela semble bien aussi –

Questions connexes