J'ai une classe où chaque méthode commence de la même manière:
class Foo {
public void bar() {
if (!fooIsEnabled) return;
//...
}
public void baz() {
if (!fooIsEnabled) return;
//...
}
public void bat() {
if (!fooIsEnabled) return;
//...
}
}
Existe-t-il un bon moyen d’exiger (et d’espérer ne pas écrire à chaque fois) la partie fooIsEnabled
pour chaque méthode publique de la classe?
Je ne connais pas le style élégant, mais voici une implémentation qui utilise le langage intégré de Java Java.lang.reflect.Proxy
cela applique que tous les appels de méthode sur Foo
commencent par vérifier le enabled
Etat.
main
méthode:
public static void main(String[] args) {
Foo foo = Foo.newFoo();
foo.setEnabled(false);
foo.bar(); // won't print anything.
foo.setEnabled(true);
foo.bar(); // prints "Executing method bar"
}
Foo
interface:
public interface Foo {
boolean getEnabled();
void setEnabled(boolean enable);
void bar();
void baz();
void bat();
// Needs Java 8 to have this convenience method here.
static Foo newFoo() {
FooFactory fooFactory = new FooFactory();
return fooFactory.makeFoo();
}
}
FooFactory
classe:
import Java.lang.reflect.InvocationHandler;
import Java.lang.reflect.Method;
import Java.lang.reflect.Proxy;
public class FooFactory {
public Foo makeFoo() {
return (Foo) Proxy.newProxyInstance(
this.getClass().getClassLoader(),
new Class[]{Foo.class},
new FooInvocationHandler(new FooImpl()));
}
private static class FooImpl implements Foo {
private boolean enabled = false;
@Override
public boolean getEnabled() {
return this.enabled;
}
@Override
public void setEnabled(boolean enable) {
this.enabled = enable;
}
@Override
public void bar() {
System.out.println("Executing method bar");
}
@Override
public void baz() {
System.out.println("Executing method baz");
}
@Override
public void bat() {
System.out.println("Executing method bat");
}
}
private static class FooInvocationHandler implements InvocationHandler {
private FooImpl fooImpl;
public FooInvocationHandler(FooImpl fooImpl) {
this.fooImpl = fooImpl;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.getDeclaringClass() == Foo.class &&
!method.getName().equals("getEnabled") &&
!method.getName().equals("setEnabled")) {
if (!this.fooImpl.getEnabled()) {
return null;
}
}
return method.invoke(this.fooImpl, args);
}
}
}
Comme d'autres l'ont déjà fait remarquer, il semble exagéré de ne plus avoir besoin de ce dont vous avez besoin si vous n'avez à vous préoccuper que de quelques méthodes.
Cela dit, il y a certainement des avantages:
Foo
n'ont pas à s'inquiéter de l'inquiétude transversale de enabled
. Au lieu de cela, le code de la méthode doit seulement s'inquiéter de l'objectif principal de la méthode, rien de plus.Foo
et, par erreur, "oublier" d’ajouter le contrôle enabled
. Le comportement de vérification de enabled
est automatiquement hérité par toute méthode récemment ajoutée.enabled
, il est très facile de le faire en toute sécurité et au même endroit.Spring
, bien que ils peuvent certainement être de bonnes options aussi.Pour être juste, certains des inconvénients sont:
FooImpl
est moche.Foo
, vous devez modifier 2 zones: la classe d'implémentation et l'interface. Ce n'est pas grave, mais il reste encore un peu de travail.EDIT:
Le commentaire de Fabian Streitel m'a fait penser à deux inconvénients avec ma solution ci-dessus, je l'avoue, je ne suis pas content de moi:
Pour résoudre le point n ° 1, et au moins atténuer le problème avec le point n ° 2, je créerais une annotation BypassCheck
(ou quelque chose de similaire) que je pourrais utiliser pour marquer les méthodes dans le Foo
interface pour laquelle je ne souhaite pas effectuer le "contrôle activé". De cette façon, je n'ai pas du tout besoin de chaînes magiques et il est beaucoup plus facile pour un développeur d'ajouter correctement une nouvelle méthode dans ce cas particulier.
En utilisant la solution d'annotation, le code ressemblerait à ceci:
main
méthode:
public static void main(String[] args) {
Foo foo = Foo.newFoo();
foo.setEnabled(false);
foo.bar(); // won't print anything.
foo.setEnabled(true);
foo.bar(); // prints "Executing method bar"
}
BypassCheck
annotation:
import Java.lang.annotation.*;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface BypassCheck {
}
Foo
interface:
public interface Foo {
@BypassCheck boolean getEnabled();
@BypassCheck void setEnabled(boolean enable);
void bar();
void baz();
void bat();
// Needs Java 8 to have this convenience method here.
static Foo newFoo() {
FooFactory fooFactory = new FooFactory();
return fooFactory.makeFoo();
}
}
FooFactory
classe:
import Java.lang.reflect.InvocationHandler;
import Java.lang.reflect.Method;
import Java.lang.reflect.Proxy;
public class FooFactory {
public Foo makeFoo() {
return (Foo) Proxy.newProxyInstance(
this.getClass().getClassLoader(),
new Class[]{Foo.class},
new FooInvocationHandler(new FooImpl()));
}
private static class FooImpl implements Foo {
private boolean enabled = false;
@Override
public boolean getEnabled() {
return this.enabled;
}
@Override
public void setEnabled(boolean enable) {
this.enabled = enable;
}
@Override
public void bar() {
System.out.println("Executing method bar");
}
@Override
public void baz() {
System.out.println("Executing method baz");
}
@Override
public void bat() {
System.out.println("Executing method bat");
}
}
private static class FooInvocationHandler implements InvocationHandler {
private FooImpl fooImpl;
public FooInvocationHandler(FooImpl fooImpl) {
this.fooImpl = fooImpl;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.getDeclaringClass() == Foo.class
&& !method.isAnnotationPresent(BypassCheck.class) // no magic strings
&& !this.fooImpl.getEnabled()) {
return null;
}
return method.invoke(this.fooImpl, args);
}
}
}
Il y a beaucoup de bonnes suggestions. Ce que vous pouvez faire pour résoudre votre problème est de penser au modèle d'état et de le mettre en œuvre.
Jetez un coup d'oeil à cet extrait de code .. peut-être que cela vous donnera une idée. Dans ce scénario, il semble que vous souhaitiez modifier toute l'implémentation des méthodes en fonction de l'état interne de l'objet. Rappelez-vous que la somme des méthodes dans un objet est connue sous le nom de comportement.
public class Foo {
private FooBehaviour currentBehaviour = new FooEnabledBehaviour (); // or disabled, or use a static factory method for getting the default behaviour
public void bar() {
currentBehaviour.bar();
}
public void baz() {
currentBehaviour.baz();
}
public void bat() {
currentBehaviour.bat();
}
public void setFooEnabled (boolean fooEnabled) { // when you set fooEnabel, you are changing at runtime what implementation will be called.
if (fooEnabled) {
currentBehaviour = new FooEnabledBehaviour ();
} else {
currentBehaviour = new FooDisabledBehaviour ();
}
}
private interface FooBehaviour {
public void bar();
public void baz();
public void bat();
}
// RENEMBER THAT instance method of inner classes can refer directly to instance members defined in its enclosing class
private class FooEnabledBehaviour implements FooBehaviour {
public void bar() {
// do what you want... when is enabled
}
public void baz() {}
public void bat() {}
}
private class FooDisabledBehaviour implements FooBehaviour {
public void bar() {
// do what you want... when is desibled
}
public void baz() {}
public void bat() {}
}
}
J'espère que vous aimez!
P.D: Est une mise en œuvre du modèle d'état (également connu sous le nom de stratégie dépendant du contexte .. mais les principes sont les mêmes).
Oui, mais c'est un peu de travail, donc cela dépend de votre importance.
Vous pouvez définir la classe en tant qu'interface, écrire une implémentation de délégué, puis utiliser Java.lang.reflect.Proxy
pour implémenter l'interface avec des méthodes qui effectuent la partie partagée puis appellent le délégué de manière conditionnelle.
interface Foo {
public void bar();
public void baz();
public void bat();
}
class FooImpl implements Foo {
public void bar() {
//... <-- your logic represented by this notation above
}
public void baz() {
//... <-- your logic represented by this notation above
}
// and so forth
}
Foo underlying = new FooImpl();
InvocationHandler handler = new MyInvocationHandler(underlying);
Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),
new Class[] { Foo.class },
handler);
Votre MyInvocationHandler
peut ressembler à quelque chose comme ceci (traitement des erreurs et échafaudage de classe omis, en supposant que fooIsEnabled
soit défini quelque part accessible):
public Object invoke(Object proxy, Method method, Object[] args) {
if (!fooIsEnabled) return null;
return method.invoke(underlying, args);
}
Ce n'est pas incroyablement joli. Mais contrairement à divers commentateurs, je le ferais, car je pense que la répétition est un risque plus important que ce genre de densité, et vous serez capable de produire le "feeling" de votre classe réelle, avec cette enveloppe un peu impénétrable ajoutée à très localement en quelques lignes de code.
Voir le documentation Java pour plus de détails sur les classes de proxy dynamiques.
Cette question est étroitement liée à programmation orientée aspect . AspectJ est une extension AOP de Java et vous pouvez y jeter un coup d'oeil pour en tirer un peu quelque chose.
Autant que je sache, il n’existe pas de support direct pour AOP en Java. Certains modèles GOF y sont associés, comme par exemple Méthode du modèle et Stratégie , mais cela ne vous sauvera pas vraiment les lignes de code.
Dans Java et dans la plupart des autres langages, vous pouvez définir la logique récurrente dont vous avez besoin dans les fonctions et adopter une approche dite de codage discipliné dans laquelle vous les appelez au bon moment.
public void checkBalance() {
checkSomePrecondition();
...
checkSomePostcondition();
}
Toutefois, cela ne conviendrait pas à votre cas, car vous souhaiteriez que le code décompacté puisse être retourné à partir de checkBalance
. Dans les langages qui supportent les macros (comme C/C++), vous pouvez définir checkSomePrecondition
et checkSomePostcondition
en tant que macros. Elles seraient simplement remplacées par le préprocesseur avant même que le compilateur ne soit appelé:
#define checkSomePrecondition \
if (!fooIsEnabled) return;
Java n’a pas cette solution prête à l'emploi. Cela peut choquer quelqu'un, mais j’ai utilisé une génération de code automatique et des moteurs de modèles pour automatiser des tâches de codage répétitives dans le passé. Si vous traitez vos fichiers Java avant de les compiler avec un préprocesseur approprié, par exemple Jinja2, vous pourriez faire quelque chose de similaire à ce qui est possible en C.
Si vous recherchez une solution pure Java, ce que vous pourrez trouver ne sera probablement pas concis. Toutefois, cela pourrait tout de même minimiser les parties communes de votre programme et éviter la duplication de code et les bugs. Vous pouvez faire quelque chose comme ceci (c'est une sorte de Stratégie - motif inspiré). Notez qu'en C # et Java 8, et dans d'autres langages dans lesquels les fonctions sont un peu plus facile à gérer, cette approche peut effectivement sembler agréable.
public interface Code {
void execute();
}
...
public class Foo {
private bool fooIsEnabled;
private void protect(Code c) {
if (!fooIsEnabled) return;
c.execute();
}
public void bar() {
protect(new Code {
public void execute() {
System.out.println("bar");
}
});
}
public void baz() {
protect(new Code {
public void execute() {
System.out.println("baz");
}
});
}
public void bat() {
protect(new Code {
public void execute() {
System.out.println("bat");
}
});
}
}
Vous développez une classe pour envoyer des trames de données à un robot industriel. Le robot prend du temps pour terminer une commande. Une fois la commande terminée, il vous renvoie une image de contrôle. Le robot peut être endommagé s'il reçoit une nouvelle commande alors que la précédente est encore en cours d'exécution. Votre programme utilise une classe DataLink
pour envoyer et recevoir des images vers et depuis le robot. Vous devez protéger l'accès à l'instance DataLink
.
Le fil de l'interface utilisateur appelle RobotController.left
, right
, up
ou down
lorsque l’utilisateur clique sur les boutons mais appelle également BaseController.tick
à intervalles réguliers, afin de réactiver le transfert de commande vers l'instance privée DataLink
.
interface Code {
void ready(DataLink dataLink);
}
class BaseController {
private DataLink mDataLink;
private boolean mReady = false;
private Queue<Code> mEnqueued = new LinkedList<Code>();
public BaseController(DataLink dl) {
mDataLink = dl;
}
protected void protect(Code c) {
if (mReady) {
mReady = false;
c.ready(mDataLink);
}
else {
mEnqueue.add(c);
}
}
public void tick() {
byte[] frame = mDataLink.readWithTimeout(/* Not more than 50 ms */);
if (frame != null && /* Check that it's an ACK frame */) {
if (mEnqueued.isEmpty()) {
mReady = true;
}
else {
Code c = mEnqueued.remove();
c.ready(mDataLink);
}
}
}
}
class RobotController extends BaseController {
public void left(float amount) {
protect(new Code() { public void ready(DataLink dataLink) {
dataLink.write(/* Create a byte[] that means 'left' by amount */);
}});
}
public void right(float amount) {
protect(new Code() { public void ready(DataLink dataLink) {
dataLink.write(/* Create a byte[] that means 'right' by amount */);
}});
}
public void up(float amount) {
protect(new Code() { public void ready(DataLink dataLink) {
dataLink.write(/* Create a byte[] that means 'up' by amount */);
}});
}
public void down(float amount) {
protect(new Code() { public void ready(DataLink dataLink) {
dataLink.write(/* Create a byte[] that means 'down' by amount */);
}});
}
}
Je considérerais le refactoring. Ce modèle casse énormément DRY (ne vous répétez pas). Je crois que cela brise cette responsabilité de classe. Mais cela dépend de votre contrôle du code. Votre question est très ouverte - où êtes-vous appelant Foo
instance?
Je suppose que tu as un code comme
foo.bar(); // does nothing if !fooEnabled
foo.baz(); // does also nothing
foo.bat(); // also
peut-être devriez-vous l'appeler quelque chose comme ceci:
if (fooEnabled) {
foo.bat();
foo.baz();
...
}
Et garde-le propre. Par exemple, en vous connectant:
this.logger.debug(createResourceExpensiveDump())
un logger
ne se demande pas, si le débogage est activé. Il suffit de se connecter.
Au lieu de cela, la classe appelante doit vérifier ceci:
if (this.logger.isDebugEnabled()) {
this.logger.debug(createResourceExpensiveDump())
}
S'il s'agit d'une bibliothèque et que vous ne pouvez pas contrôler l'appel de cette classe, lancez un IllegalStateException
qui explique pourquoi, si cet appel est illégal et cause des problèmes.
À mon humble avis, la solution la plus élégante et la plus performante à cet égard consiste à avoir plusieurs implémentations de Foo, ainsi qu'une méthode d'usine permettant d'en créer une:
class Foo {
protected Foo() {
// Prevent direct instantiation
}
public void bar() {
// Do something
}
public static void getFoo() {
return fooEnabled ? new Foo() : new NopFoo();
}
}
class NopFoo extends Foo {
public void bar() {
// Do nothing
}
}
Ou une variante:
class Foo {
protected Foo() {
// Prevent direct instantiation
}
public void bar() {
// Do something
}
public static void getFoo() {
return fooEnabled ? new Foo() : NOP_FOO;
}
private static Foo NOP_FOO = new Foo() {
public void bar() {
// Do nothing
}
};
}
Comme le fait remarquer sstan, il serait préférable d'utiliser une interface:
public interface Foo {
void bar();
static Foo getFoo() {
return fooEnabled ? new FooImpl() : new NopFoo();
}
}
class FooImpl implements Foo {
FooImpl() {
// Prevent direct instantiation
}
public void bar() {
// Do something
}
}
class NopFoo implements Foo {
NopFoo() {
// Prevent direct instantiation
}
public void bar() {
// Do nothing
}
}
Adaptez cela au reste de votre situation (créez-vous un nouveau Foo à chaque fois ou réutilisez-vous la même instance, etc.)
J'ai une autre approche: avoir un
interface Foo {
public void bar();
public void baz();
public void bat();
}
class FooImpl implements Foo {
public void bar() {
//...
}
public void baz() {
//...
}
public void bat() {
//...
}
}
class NullFoo implements Foo {
static NullFoo DEFAULT = new NullFoo();
public void bar() {}
public void baz() {}
public void bat() {}
}
}
et alors vous pouvez faire
(isFooEnabled ? foo : NullFoo.DEFAULT).bar();
Peut-être pourriez-vous même remplacer le isFooEnabled
par une variable Foo
qui contient le FooImpl
à utiliser ou le NullFoo.DEFAULT
. Ensuite, l'appel est à nouveau plus simple:
Foo toBeUsed = isFooEnabled ? foo : NullFoo.DEFAULT;
toBeUsed.bar();
toBeUsed.baz();
toBeUsed.bat();
BTW, cela s'appelle le "modèle nul".
Dans une approche fonctionnelle similaire à la réponse de @ Colin, avec fonctions lambda de Java 8 , il est possible d’envelopper le code d’activation/désactivation conditionnelle dans une méthode Guard (executeIfEnabled
) qui accepte l'action lambda, à laquelle le code à exécuter conditionnellement peut être passée.
Bien que, dans votre cas, cette approche ne sauvegarde aucune ligne de code, vous pouvez désormais centraliser d'autres problèmes de bascule de fonctionnalités, ainsi que des problèmes de débogage, tels que la journalisation, les diagnostics, le profilage, etc.
L'un des avantages de l'utilisation de lambdas ici est que les fermetures peuvent être utilisées pour éviter le besoin de surcharger la méthode executeIfEnabled
.
Par exemple:
class Foo {
private Boolean _fooIsEnabled;
public Foo(Boolean isEnabled) {
_fooIsEnabled = isEnabled;
}
private void executeIfEnabled(Java.util.function.Consumer someAction) {
// Conditional toggle short circuit
if (!_fooIsEnabled) return;
// Invoke action
someAction.accept(null);
}
// Wrap the conditionally executed code in a lambda
public void bar() {
executeIfEnabled((x) -> {
System.out.println("Bar invoked");
});
}
// Demo with closure arguments and locals
public void baz(int y) {
executeIfEnabled((x) -> {
System.out.printf("Baz invoked %d \n", y);
});
}
public void bat() {
int z = 5;
executeIfEnabled((x) -> {
System.out.printf("Bat invoked %d \n", z);
});
}
Avec un test:
public static void main(String args[]){
Foo enabledFoo = new Foo(true);
enabledFoo.bar();
enabledFoo.baz(33);
enabledFoo.bat();
Foo disabledFoo = new Foo(false);
disabledFoo.bar();
disabledFoo.baz(66);
disabledFoo.bat();
}
Comme indiqué dans d'autres réponses, le modèle de conception de stratégie est un modèle de conception approprié à suivre pour simplifier ce code. Je l'ai illustré ici en utilisant l'invocation de méthode par réflexion, mais vous pouvez utiliser un certain nombre de mécanismes pour obtenir le même effet.
class Foo {
public static void main(String[] args) {
Foo foo = new Foo();
foo.fooIsEnabled = false;
foo.execute("bar");
foo.fooIsEnabled = true;
foo.execute("baz");
}
boolean fooIsEnabled;
public void execute(String method) {
if(!fooIsEnabled) {return;}
try {
this.getClass().getDeclaredMethod(method, (Class<?>[])null).invoke(this, (Object[])null);
}
catch(Exception e) {
// best to handle each exception type separately
e.printStackTrace();
}
}
// Changed methods to private to reinforce usage of execute method
private void bar() {
System.out.println("bar called");
// bar stuff here...
}
private void baz() {
System.out.println("baz called");
// baz stuff here...
}
private void bat() {
System.out.println("bat called");
// bat stuff here...
}
}
Si seulement Java était un peu meilleur pour être fonctionnel. Il pense que la solution la plus OOO est de créer une classe qui englobe une fonction unique de sorte qu'elle ne soit appelée que lorsque foo est activé.
abstract class FunctionWrapper {
Foo owner;
public FunctionWrapper(Foo f){
this.owner = f;
}
public final void call(){
if (!owner.isEnabled()){
return;
}
innerCall();
}
protected abstract void innerCall();
}
puis implémenter bar
, baz
et bat
en tant que classes anonymes qui étendent FunctionWrapper
.
class Foo {
public boolean fooIsEnabled;
public boolean isEnabled(){
return fooIsEnabled;
}
public final FunctionWrapper bar = new FunctionWrapper(this){
@Override
protected void innerCall() {
// do whatever
}
};
public final FunctionWrapper baz = new FunctionWrapper(this){
@Override
protected void innerCall() {
// do whatever
}
};
// you can pass in parms like so
public final FunctionWrapper bat = new FunctionWrapper(this){
// some parms:
int x,y;
// a way to set them
public void setParms(int x,int y){
this.x=x;
this.y=y;
}
@Override
protected void innerCall() {
// do whatever using x and y
}
};
}
Une autre idée
Utilisez la solution nullable de glglgl mais créez FooImpl
et NullFoo
classes internes (avec constructeurs privés) de la classe ci-dessous:
class FooGateKeeper {
public boolean enabled;
private Foo myFooImpl;
private Foo myNullFoo;
public FooGateKeeper(){
myFooImpl= new FooImpl();
myNullFoo= new NullFoo();
}
public Foo getFoo(){
if (enabled){
return myFooImpl;
}
return myNullFoo;
}
}
de cette façon, vous n'avez pas à vous soucier de vous rappeler d'utiliser (isFooEnabled ? foo : NullFoo.DEFAULT)
.
Java. Supposons qu’en Java, il existe polymorphisme, propriété statique, classe abstraite et méthode:
public static void main(String[] args) {
Foo.fooIsEnabled = true; // static property, not particular to a specific instance
Foo foo = new bar();
foo.mainMethod();
foo = new baz();
foo.mainMethod();
foo = new bat();
foo.mainMethod();
}
public abstract class Foo{
static boolean fooIsEnabled;
public void mainMethod()
{
if(!fooIsEnabled)
return;
baMethod();
}
protected abstract void baMethod();
}
public class bar extends Foo {
protected override baMethod()
{
// bar implementation
}
}
public class bat extends Foo {
protected override baMethod()
{
// bat implementation
}
}
public class baz extends Foo {
protected override baMethod()
{
// baz implementation
}
}
Il semble que la classe ne fasse rien quand Foo n'est pas activé, alors pourquoi ne pas l'exprimer à un niveau supérieur où vous créez ou obtenez l'instance de Foo?
class FooFactory
{
static public Foo getFoo()
{
return isFooEnabled ? new Foo() : null;
}
}
...
Foo foo = FooFactory.getFoo();
if(foo!=null)
{
foo.bar();
....
}
Cela ne fonctionne que si isFooEnabled est une constante. Dans un cas général, vous pouvez créer votre propre annotation.
En gros, vous indiquez que, s’il est défini, l’appel de fonction doit être ignoré. Je pense donc que ma solution serait idiote, mais la voici.
Foo foo = new Foo();
if (foo.isEnabled())
{
foo.doSomething();
}
Voici l'implémentation d'un proxy simple, au cas où vous voudriez exécuter du code avant d'exécuter une fonction.
class Proxy<T>
{
private T obj;
private Method<T> proxy;
Proxy(Method<T> proxy)
{
this.ojb = new T();
this.proxy = proxy;
}
Proxy(T obj, Method<T> proxy)
{
this.obj = obj;
this.proxy = proxy;
}
public T object ()
{
this.proxy(this.obj);
return this.obj;
}
}
class Test
{
public static void func (Foo foo)
{
// ..
}
public static void main (String [] args)
{
Proxy<Foo> p = new Proxy(Test.func);
// how to use
p.object().doSomething();
}
}
class Foo
{
public void doSomething ()
{
// ..
}
}
Il existe une autre solution, en utilisant delegate (pointeur vers fonction). Vous pouvez avoir une méthode unique qui commence par effectuer la validation puis appelle la méthode correspondante en fonction de la fonction (paramètre) à appeler. Code C #:
internal delegate void InvokeBaxxxDelegate();
class Test
{
private bool fooIsEnabled;
public Test(bool fooIsEnabled)
{
this.fooIsEnabled = fooIsEnabled;
}
public void Bar()
{
InvokeBaxxx(InvokeBar);
}
public void Baz()
{
InvokeBaxxx(InvokeBaz);
}
public void Bat()
{
InvokeBaxxx(InvokeBat);
}
private void InvokeBaxxx(InvokeBaxxxDelegate invoker)
{
if (!fooIsEnabled) return;
invoker();
}
private void InvokeBar()
{
// do Invoke bar stuff
Console.WriteLine("I am Bar");
}
private void InvokeBaz()
{
// do Invoke bar stuff
Console.WriteLine("I am Baz");
}
private void InvokeBat()
{
// do Invoke bar stuff
Console.WriteLine("I am Bat");
}
}