2009-05-30 9 views
1

Imaginez une application basée sur des options.Se débarrasser du fardeau de la vérification de la valeur d'un paramètre chaque fois qu'un objet est utilisé

Je veux ajouter un point d'exclamation à la fin de chaque chaîne (elle-même, une tâche extrêmement facile). Cependant, j'ai une option dans web.config ou un fichier XML, donc si l'option est true, l'exclamation est ajoutée, sinon ce n'est pas le cas.

Je sais comment vérifier web.config ou un fichier xml pour la valeur du paramètre, cependant, quelle est la meilleure façon de le faire? Dans le cas d'une chaîne, il sera fortement utilisé dans n'importe quel programme.

Je pourrais écrire:

if (ExclamationIsSet) 
{ 
// Append here 
} 

// Otherwise it isn't set, so don't. 

Cependant, ce n'est pas pratique pour un grand (ou même petite) codebase. Y a-t-il un moyen de se débarrasser de cette vérification manuelle? J'ai entendu AOP ou attributs peuvent être en mesure de résoudre ce problème, mais je n'ai pas vu un exemple.

Quelles méthodes pourraient résoudre ce problème?

Répondre

4

l'opération peut être décrite comme:

public interface ITextDecorator 
{ 
    string GetString(string input); 
} 

Cette encapsule le comment (Web.config, XML, etc.) et souligne le ce (décorer une chaîne).

Ensuite, toute classe qui pourrait avoir besoin pour décorer le texte peut prendre une instance de cette interface:

public class Foo 
{ 
    private ITextDecorator _textDecorator; 

    public Foo(ITextDecorator textDecorator) 
    { 
     _textDecorator = textDecorator; 
    } 

    public void Bar(string text) 
    { 
     text = _textDecorator.GetString(text); 

     // ... 
    } 
} 

implémentations Exemple de ITextDecorator pourraient être:

public sealed class ExclamationPointTextDecorator : ITextDecorator 
{ 
    public string GetString(string input) 
    { 
     return input + "!"; 
    } 
} 

public sealed class ConditionalTextDecorator : ITextDecorator 
{ 
    private Func<bool> _condition; 
    private ITextDecorator _innerTextDecorator; 

    public ConditionalTextDecorator(Func<bool> condition, ITextDecorator innerTextDecorator) 
    { 
     _condition = condition; 
     _innerTextDecorator = innerTextDecorator; 
    } 

    public string GetString(string input) 
    { 
     return _condition() ? _innerTextDecorator.GetString(input) : input; 
    } 
} 

Un exemple d'utilisation de ces classes pourraient être:

var textDecorator = new ConditionalTextDecorator(
    () => true, // Check Web.config, an XML file, or any other condition 
    new ExclamationPointTextDecorator()); 

var foo = new Foo(textDecorator); 

foo.Bar("Test"); 

Notez que le découplage de la exclamat point d'ion venant de son invocation conditionnelle. Les deux classes peuvent maintenant être réutilisées indépendamment l'une de l'autre.Ce style de conception d'objets fins fonctionne mieux avec un conteneur Inversion of Control (IoC). Cependant, ce n'est pas obligatoire.

2

Je n'utiliserais probablement pas AOP ici ... ma question est: quand faites-vous cet ajout? Je voudrais simplement brancher dans une méthode d'utilité à ce point - à savoir

WriteOutput(someValue); // presumably with some other args 

WriteOutput a la charge de vérifier ce drapeau - à-dire qu'il est pas dans beaucoup des lieux. Vous pouvez également trouver que les méthodes d'extension C# 3.0 ont un rôle à jouer; par exemple, si vous écrivez à un TextWriter:

public static void WriteWithMarker(this TextWriter writer, SomeType value) { 
    writer.Write(value); 
    if(ExclamationIsSet) writer.Write(SomeExtraStuff); 
} 

alors votre code juste (toujours) appelle output.WriteWithMarker(value); - fait travail.

Je probablement aussi assurer que je minimiser l'impact en stockant cette valeur une fois à initialisation - constructeurs statiques sont tout à fait à portée de main pour que:

public static class MyUtiltiyClass { 
    private static readonly bool exclamationIsSet; 
    public static bool ExclamationIsSet {get{return exclamationIsSet;}} 
    static MyUtiltiyClass() { 
     exclamationIsSet = FindWhetherTheFlagIsSet(); 
    } 
    public static void WriteWithMarker(this TextWriter writer, SomeType value) { 
     writer.Write(value); 
     if(ExclamationIsSet) writer.Write(SomeExtraStuff); 
    } 
    //etc 
} 

Peut-être avec plus de contexte sur quoi et où vous faites actuellement cela, il pourrait deviennent plus clairs ....

+0

+1 pour la procédure détaillée. – dotnetdev

2

Vous pouvez envelopper le chèque dans une méthode:

private string SomeGoodMethodName(string text) 
{ 
    if (text == null || text.EndsWith("!")) { return text; } 

    return ConfigurationManager.AppSettings["addExclamation"] == "1" ? text + "!" : text; 
} 

... puis aller chercher vos cordes par cette méthode. Si nécessaire, vous pouvez vous intéresser à la performance autour de ConfigurationManager.AppSettings et peut-être stocker cela comme un booléen à tester à la place.

+0

J'adore le nom SomeGoodMethodName ;-p –

+0

: o) Impossible d'en trouver un bon, alors j'ai laissé ça à l'imagination des lecteurs. –

+0

C'est probablement le meilleur moyen - très rapide aussi. Je suis content d'avoir fait ce fil car il m'a empêché de regarder quelque chose de potentiellement inutile (par exemple AOP). – dotnetdev

Questions connexes