2009-11-13 2 views
1

Dans mon programme, il y a un endroit où j'ai besoin d'accéder à un singleton résolu d'une usine et le joindre à son événement:Attachement à un événement singleton instancié en usine - quelle serait une approche propre?

void MyMethod() 
{ 
    myFactory.Resolve<MySingleton>().DoWork += WorkMethod; 
} 

Le problème est que MyMethod peut être exécuté plusieurs fois, mais je veux joindre à l'événement qu'une seule fois (sinon j'obtiendrai plusieurs appels). Donc, je veux attacher seulement quand je n'étais pas attaché avant. Il n'y a rien nicier que

myFactory.Resolve<MySingleton>().DoWork -= WorkMethod; 
    myFactory.Resolve<MySingleton>().DoWork += WorkMethod; 

Répondre

5

Qu'en est-il un certain drapeau à retenir si MyMethod a déjà été appelé pour le singleton?

object myCachedSingleton = null; 

void MyMethod() 
{ 
    var s = myFactory.Resolve<MySingleton>(); 
    if (myCachedSingleton == s) return; 
    myCachedSingleton = s; 
    myCachedSingleton.DoWork += WorkMethod; 
} 
+0

Vous pouvez placer l'événement et la logique 'hasBeenCalled' dans une méthode privée. Je le fais habituellement pour l'enlever de MyMethod(). Si vous avez de nombreux événements, cela encombre la méthode originale. – TheSean

+0

Je pense que c'est une bonne approche, mais mon singleton n'est pas un singleton "à vie". Parfois, il peut être recréé, donc il semble que, à la place du drapeau, je devrais utiliser une référence à celui-ci. –

0

Vous pouvez également consulter l'InvocationList pour voir si quelque chose a été attaché à l'événement.

Modifié pour utiliser une action, vous n'avez donc pas besoin de passer une chaîne magique.

Exemple:

public bool IsAttached(Action<string> methodToCheck) 
{ 
    SomeWork completed = DoWork; 
    return completed.GetInvocationList().Any(m => m.Method.Name == methodToCheck.Method.Name); 
} 

Utilisation:

var b = new FooBar(); 
    b.DoWork += b_OnWorkCompleted; 
    b.DoWork += c_OnWorkCompleted; 

    Console.WriteLine(b.IsAttached(c_OnWorkCompleted)); 
    Console.WriteLine(b.IsAttached(b_OnWorkCompleted)); 
    Console.WriteLine(b.IsAttached(FooBar)); 

sortie serait true, true, false

1

Selon la façon dont Couplé vous voulez que ces types soient, vous pouvez joindre à l'événement en statique constructeur. Ensuite, il ne serait possible d'être exécuté qu'une seule fois (par AppDomain je pense). Quelque chose comme ceci:

public class MyConsumer 
{ 
    static MyConsumer() 
    { 
     Factory.Resolve<Singleton>().DoWork += WorkMethod; 
    } 

    private static void WorkMethod(...) { ... } 
} 

La (sur) l'utilisation de méthodes statiques est un peu rebutant, mais en fonction de vos besoins qui peuvent être ok.

Je vais juste ajouter que les autres réponses ici sont également bien, mais assurez-vous de penser à tout problème de threading.

0

Je veux juste mettre l'approche je dans la question pour le vote, aussi - si vous n'êtes pas d'accord, voter contre ...

Y at-il quelque chose de mal avec

var singleton = myFactory.Resolve<MySingleton>(); 
singleton.DoWork -= WorkMethod; 
singleton.DoWork += WorkMethod; 

???

Questions connexes