Frage

Ich bin neu in C # (begann letzte Woche) so cool mit mir;). Ich würde gerne wissen, ob ich irgendwie eine benutzerdefinierte Eigenschaft schreiben, lassen Sie mich erklären:

Ich habe einige partielle Klassen, die ich durch Hinzufügen von Eigenschaften abgeschlossen haben, aber das Muster aller Getter und Setter sind die gleichen, so würde Ich mag diese faktorisieren:

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;
        }
    }
}

Wie Sie sehen können, ist die einzige Sache, die Änderung Ressource1 / Ressource2 ist. Mein Ziel ist in der Lage sein, etwas zu schreiben wie:

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

    public LocalizedString TravelDescription(Ressource2);
}

Wer eine Idee hat, diese zu machen, oder eine andere Idee zu meinem Code sauberer zu machen? Vielen Dank,

Guillaume

War es hilfreich?

Lösung

Es gibt keine Möglichkeit, diese innerhalb von C # oder .NET selbst zu tun, aber wenn man viel davon machen kann es sich lohnt Aspekt orientierte Programmierung durch die Untersuchung Postsharp . Grundsätzlich wird es ermöglicht es Ihnen, ein Attribut zu definieren, die zusätzliche Code verursacht bei der Kompilierung zu injizieren. Der Code, den Sie geben so etwas wie:

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

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

Und bei der Kompilierung Postsharp wird die Eigenschaft mit einer Vorlage ersetzen Sie in der neuen LocalizedPropertyAttribute Klasse definiert haben.

Andere Tipps

Sie können nicht machen es ganz so knapp wie das, was Sie beschreiben, aber Sie können die Komplexität und die Redundanz der Einrichter verringern.

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); }
}

Ich weiß nicht genau, was Sie erreichen wollen, aber Sie können zu kompliziert die Dinge werden. Wäre dies nicht ausreichend sein?

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; }
}

, wo Ressourcen ist eine generierte Klasse (aus einer resx-Datei) für lokalisierte Ressourcen. Ich habe das Gefühl, Sie versuchen, Ihre eigene Lokalisierung Rahmen zu bauen, weil Sie noch nicht wissen, dass .NET bereits Infrastruktur für die .

Nein, es gibt keine solche Art und Weise. Es wäre möglich in PHP aber nicht in C #.

Sie sollten Ihren Ansatz weg in diesem Fall von Eigenschaften ändern.

UPD: Wahrscheinlich könnte man so etwas für jede Eigenschaft (außer es ist offensichtlich, Schwäche):

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;
        }
}

Sie können eine einzelne indizierte Eigenschaft implementieren, können Sie eine der folgenden zwei Syntax Entscheidungen auf der Grundlage Ihrer Präferenz zu geben. Der Code würde im Grunde eine Funktion sein, die die speziell benannte Ressource und gibt den richtigen Inhalt akzeptiert.

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

Sie können Ihr Leben einfacher durch Einkapseln Ihre Getter und Setter-Logik in einer Basisklasse machen und dann einfach diese Methoden aus neuen Eigenschaften aufrufen Sie erstellen (einfach als dünne Hülle um diesen Verfahren handelt). Hier ein Beispiel:

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;
    }

}

... Auf diese Weise gibt es sehr wenig Logik in Ihren Eigenschaften und Sie wiederholen weniger Code. Dies setzt voraus, die folgenden Klassen (die ich als genericized verspottet):

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

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

Das macht keinen Sinn. mit propertys so, wie Sie sie derzeit haben, können Sie einfach schreiben:

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

Wenn Sie auf die Art und Weise geändert Sie möchten, müssten die Parameter auch angeben

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

alles, was Sie tun können, ist ein "PropertyBag" Emulator machen

   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; }
       }
   }

Sie möchten Zugriff auf diese wie folgt aus:

   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];    
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top