簡體   English   中英

是否可以“擴展”財產“類”?

[英]Is it possible to “extend” the property “class”?

我是C#的新手(上周開始),所以對我很冷靜;)。 我想知道我是否能以某種方式編寫自定義屬性,讓我解釋一下:

我有一些部分類,我通過添加屬性完成,但所有getter和setter的模式是相同的,所以我想分解這個:

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

正如您所看到的,唯一改變的是Ressource1 / Ressource2。 我的目標是能夠寫出如下內容:

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

    public LocalizedString TravelDescription(Ressource2);
}

有人有想法讓這個或其他想法讓我的代碼更干凈嗎? 謝謝,

紀堯姆

在C#或.NET本身內沒有設施可以做到這一點,但是如果你正在做很多這樣的事情,那么通過postharp調查面向方面的編程可能是值得的。 基本上它允許您定義一個屬性,該屬性導致在編譯時注入額外的代碼。 您輸入的代碼如下:

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

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

在編譯時,PostSharp將使用您在新LocalizedPropertyAttribute類中定義的模板替換該屬性。

你不能讓它簡明扼要你的描述,但可以降低的setter方法的復雜性和冗余。

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

我不確切地知道你想要實現什么,但你可能會讓事情變得太復雜。 這不夠嗎?

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

其中Resources是本地化資源的生成類(來自resx文件)。 我有一種感覺,你正在嘗試構建自己的本地化框架,因為你還不知道.NET 已經有了基礎設施

不,沒有這樣的方式。 可能在PHP中,但不在C#中。

在這種情況下,您應該改變您的方法遠離屬性。

UPD:可能你可以為每個屬性使用這樣的東西(除了它明顯的弱點):

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

您可以實現單個索引屬性,根據您的偏好為您提供以下兩種語法選擇之一。 代碼基本上是一個接受特定命名資源並返回正確內容的函數。

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

通過將getter和setter邏輯封裝在基類中,然后從您創建的任何新屬性中調用這些方法(簡單地充當這些方法的瘦包裝器),您可以使您的生活更輕松。 這是一個例子:

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

}

...這樣,您的屬性中的邏輯很少,並且您重復的代碼更少。 這假設以下類(我嘲笑為通用化):

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

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

這沒有意義。 使用propertys就像你現在擁有它們一樣,你可以簡單地寫:

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

如果您更改為您想要的方式,則還必須指定參數

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

你所能做的就是做一個“propertyBag”模擬器

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

您可以這樣訪問:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM