Question

Je suis nouveau en C # (commencé la semaine dernière) alors soyez sympa avec moi;). J'aimerais savoir si je peux en quelque sorte écrire une propriété personnalisée, laissez-moi vous expliquer:

J'ai quelques classes partielles que je complète en ajoutant des propriétés, mais le modèle de tous les getters et les setters est le même, je voudrais donc factoriser ceci:

public partial class Travel
{
    public String TravelName
    {
        get
        {
            return LocaleHelper.GetRessource(Ressource1);
        }
        set
        {
            if (this.Ressource1 == null)
                Ressource1 = new Ressource() { DefaultValue = value };
            else
                Ressource1.DefaultValue = value;
        }
    }

    public String TravelDescription
    {
        get
        {
            return LocaleHelper.GetRessource(Ressource2);
        }
        set
        {
            if (this.Ressource2 == null)
                Ressource2 = new Ressource() { DefaultValue = value };
            else
                Ressource2.DefaultValue = value;
        }
    }
}

Comme vous pouvez le constater, la seule chose qui change est Ressource1 / Ressource2. Mon objectif est de pouvoir écrire quelque chose comme:

public partial class Travel
{
    public LocalizedString TravelName(Ressource1);

    public LocalizedString TravelDescription(Ressource2);
}

Quelqu'un a une idée pour rendre ceci, ou une autre idée pour rendre mon code plus propre? Merci,

Guillaume

Était-ce utile?

La solution

Il n’existe aucune installation permettant de faire cela dans C # ou .NET, mais si vous en faites beaucoup, il peut être intéressant d’examiner la programmation orientée vers les aspects via postsharp . En gros, cela vous permettra de définir un attribut qui injectera du code supplémentaire lors de la compilation. Le code que vous tapez est quelque chose comme:

public partial class Travel
{
    [LocalizedProperty(source = "Ressource1")
    public string TravelName { get; set; }

    [LocalizedProperty(source = "Ressource2")
    public string TravelDescription{ get; set; }
}

Et au moment de la compilation, PostSharp remplacera la propriété par un modèle que vous avez défini dans la nouvelle classe LocalizedPropertyAttribute.

Autres conseils

Vous ne pouvez pas le rendre assez aussi succinct que ce que vous décrivez, mais vous pouvez réduire la complexité et la redondance des paramètres.

private void SetRessource(ref Ressource res, string value)
{
    if(res == null) res = new Ressource();

    res.DefaultValue = value;
}

public String TravelName
{
    get { return LocaleHelper.GetRessource(Ressource1); }
    set { SetRessource(ref this.Ressource1, value); }
}

public String TravelDescription
{
    get { return LocaleHelper.GetRessource(Ressource2); }
    set { SetRessource(ref this.Ressource2, value); }
}

Je ne sais pas exactement ce que vous essayez de réaliser, mais vous compliquez peut-être les choses. Cela ne suffirait-il pas?

public class Travel
{
   /// <summary>
   /// Creates a new instance of <see cref="Travel"/>.
   /// </summary>
   public Travel()
   {
      this.TravelName = Resources.DefaultTravelName;
      this.TravelDescription = Resources.DefaultTravelDescription;
   }

   public string TravelName { get; set; }

   public string TravelDescription { get; set; }
}

où Ressources est une classe générée (à partir d'un fichier resx) pour les ressources localisées. J'ai l'impression que vous essayez de créer votre propre infrastructure de localisation, car vous ne savez pas encore que .NET possède déjà une infrastructure pour cela .

Non, il n'y en a pas. Ce serait possible en php , mais pas en C #.

Dans ce cas, vous devez modifier votre approche en vous éloignant des propriétés.

UPD: Vous pourriez probablement utiliser quelque chose comme ceci pour chaque propriété (à l'exception de sa faiblesse évidente):

public class Prop
{
    Resource _res;

    public Prop(Resource res)
    {
        this._res = res;
    }

    public string Value
    {
        get
        {
            return LocaleHelper.GetRessource(_res);
        }
        set
        {
            if(_res == null)
                // This is a weak point as it's now
                // as it wont work
            else
                _res.DefaultValue = value;
        }
}

Vous pouvez implémenter une propriété indexée unique en vous donnant l’un des deux choix de syntaxe suivants en fonction de vos préférences. Le code serait essentiellement une fonction qui accepte la ressource nommée spécifiquement et renvoie le bon contenu.

Travel t = new Travel();
string x = t["Name"];
    or 
string x = t[Travel.Name];

Vous pourriez vous simplifier la vie en encapsulant votre logique d’acquisition et de définition dans une classe de base, puis en appelant simplement ces méthodes à partir de toutes les nouvelles propriétés que vous créez (agissant simplement comme un bouclier autour de ces méthodes). Voici un exemple:

public class Travel : LocalizedRessourceSubscriber
{

    private Ressource<string> Ressource1 = null;
    private Ressource<string> Ressource2 = null;

    public String TravelName { 
        get { return GetRessource<string>(Ressource2); }
        set { SetRessource<string>(Ressource1, value); } 
    }

    public String TravelDescription {
        get { return GetRessource<string>(Ressource2); }
        set { SetRessource<string>(Ressource2, value); } 
    }

}

public class LocalizedRessourceSubscriber
{

    protected T GetRessource<T>(Ressource<T> Source)
    {
        return LocaleHelper.GetRessource<T>(Source);
    }

    protected void SetRessource<T>(Ressource<T> Source, T Value)
    {
       (Source ?? 
           (Source = new Ressource<T>())
                ).DefaultValue = Value;
    }

}

... De cette façon, il y a très peu de logique dans vos propriétés et vous répétez moins de code. Cela suppose les classes suivantes (que j'ai simulées en tant que génériques):

public static class LocaleHelper
{
    public static T GetRessource<T>(Ressource<T> Source)
    {
        return default(T);
    }
}

public class Ressource<T>
{
    public T DefaultValue { get; set; }
}

Cela n’a aucun sens. en utilisant les propriétés telles que vous les avez actuellement, vous pouvez simplement écrire:

   Travel t = new Travel();
   string tvlName = t.TravelName;    
   string desc = t.TravelDescription;

Si vous avez changé comme vous le souhaitez, vous devez également spécifier le paramètre

   Travel t = new Travel();
   LocalizedString tvlName = t.TravelName([someresopurcedesignator]);    
   LocalizedString desc = t.TravelDescription([someresopurcedesignator]);  

Tout ce que vous pouvez faire est de créer un " propertyBag " émulateur

   public class Travel 
   {
       private LocalizedString props = new LocalizedString();
       public LocalizedString Propertys
       {
          get { return props; }
          set { props = value; }
       }

   }

   public class LocalizedString // this is property Bag emulator
   {
       public string this[string resourceName]
       {
           get{ return LocaleHelper.GetRessource(resourceName); }
           set{ LocaleHelper.GetRessource(resourceName) = value; }
       }
   }

Vous accéderiez à ceci comme ceci:

   Travel t = new Travel();
   t.Propertys[NameResource1] = "Bob Smith";
   t.Propertys[DescriptionResource2] = "Fun trip to discover the orient";
   string tvlName = t.Propertys[NameResource1];    
   string desc    = t.Propertys[DescriptionResource2];    
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top