2009-09-11 3 views
4

Я новичок в C# (начался на прошлой неделе), так что будьте круты со мной;). Я хотел бы знать, могу ли я как-то написать собственное свойство, позвольте мне объяснить:Возможно ли «расширить» свойство «класс»?

У меня есть частичные классы, которые я заполняю, добавляя свойства, но шаблон всех геттеров и сеттеров одинаковый, поэтому я бы хотели факторизовать это:

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

Кто-нибудь есть идея, чтобы сделать это, или еще одна идея, чтобы сделать свой код понятнее? Спасибо,

Гийома

+0

Знаете ли вы, что пространство/понятия System.Globalization? –

+0

Да, но то, что я нашел в Интернете об использовании базы данных для хранения данных ressource, очень «запутанно» (головная боль) ... – Guillaume86

ответ

7

Там нет возможности сделать это внутри C# или сам .NET, но если вы многие из них могут стоить исследовать ориентированное на аспект программирование через postsharp. В основном это позволит вам определить атрибут, который вызывает добавление дополнительного кода во время компиляции. Код типа быть что-то вроде:

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

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

И во время компиляции PostSharp заменит свойство с помощью шаблона вы определили в новом классе LocalizedPropertyAttribute.

+0

Спасибо за ваш ответ, я попробую это;) – Guillaume86

0

Нет, нет такого способа. Это будет possible in 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; 
     } 
} 
-1

Это не имеет смысла. используя 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];  
+0

Еще раз посмотрим на сеттера на указатель LocalizedString ... –

+0

Я думаю, вы неправильно поняли намерение OPs. Его синтаксис не предполагает, что вызовы свойства становятся параметризованными; он просто хочет, чтобы реализация была параметризована. –

+0

@Jeff, Тогда, возможно, я до сих пор не понимаю ... Если реализация параметризуется, как может значение параметра получить в реализации, если вызовы не параметризуются? –

3

Вы не можете сделать это довольно как лаконично, как то, что вы описали, но вы можете уменьшить сложность и избыточность сеттеров.

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

Хорошая идея. Дополнительное предложение состоит в том, чтобы сделать элемент get, set и Ressource частью интерфейса, скажем, INameProvider. – mjv

0

Вы можете реализовать одно индексированное свойство, предоставив вам один из следующих двух вариантов синтаксиса, основанный на ваших предпочтениях. Код в основном будет функцией, которая принимает специально названный ресурс и возвращает правильный контент.

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

Я не знаю точно, чего вы пытаетесь достичь, но вы можете сделать что-то слишком сложным. Разве этого было бы недостаточно?

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

где Ресурсы - сгенерированный класс (из файла resx) для локализованных ресурсов. У меня такое чувство, что вы пытаетесь создать свою собственную локализацию, потому что еще не знаете, что .NET already has infrastructure for that.

+0

На самом деле Ressources являются объектами Linq to SQL с полями «en», «fr», «es» и т. Д. Строковые. My LocaleHelper.GetRessource (Ressource) возвращает правильный язык. (Мне нужно иметь ресурсы rusources в базе данных, и я попытался использовать систему глобализации по умолчанию, это ад, чтобы использовать db вместо resx ...). Мои пользовательские свойства, которые позволяют мне делать приятные запросы LINQ и привязки данных. – Guillaume86

+0

btw ваше решение идеально подходит для получения части, но, к сожалению, сложная часть немного сложнее ... – Guillaume86

0

Вы можете сделать вашу жизнь проще, инкапсулируя логику 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; } 
} 
Смежные вопросы