Pergunta

Eu sou novo para C # (começou na semana passada) para ser legal comigo;). Eu gostaria de saber se eu posso de alguma forma escrever uma propriedade personalizada, deixe-me explicar:

Eu tenho algumas classes parciais que eu completar adicionando propriedades, mas o padrão de todos os getters e setters são os mesmos, então eu gostaria de fatorar isto:

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

Como você pode ver, a única coisa que a mudança é Ressource1 / Ressource2. Meu objetivo é ser capaz de escrever algo como:

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

    public LocalizedString TravelDescription(Ressource2);
}

Alguém tem uma idéia para fazer isso, ou outra idéia para fazer o meu código mais limpo? Obrigado,

Guillaume

Foi útil?

Solução

Não existe a possibilidade de fazer isso dentro C # ou .NET em si, mas se você está fazendo muitos destes pode valer a pena investigar aspecto programação orientada através de PostSharp . Basicamente, ele irá permitir que você definir um atributo que faz com que código extra para ser injetado em tempo de compilação. O código que você digita ser algo como:

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

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

E em tempo de compilação PostSharp irá substituir a propriedade com um modelo que você definiu na nova classe LocalizedPropertyAttribute.

Outras dicas

Você não pode fazê-lo muito tão sucinto quanto o que você descreve, mas você pode diminuir a complexidade e redundância dos setters.

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

Eu não sei exatamente o que você está tentando alcançar, mas você pode estar fazendo as coisas muito complicadas. Isso não seria suficiente?

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

Onde os recursos é uma classe gerada (de um arquivo resx) para recursos localizados. Tenho a sensação de que você está tentando construir sua própria estrutura de localização, porque você não sabe ainda que o .NET já tem infra-estrutura para que .

Não, não há nenhuma maneira. Seria possível em php mas não em C #.

Você deve alterar a sua abordagem longe de propriedades neste caso.

UPD: Provavelmente você poderia usar algo como isto para cada propriedade (exceto para a sua fraqueza óbvia):

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

Você poderia implementar uma única propriedade indexada, dando-lhe uma das seguintes duas opções de sintaxe com base em suas preferências. O código seria basicamente uma função que aceita o recurso especificamente chamado e retorna o conteúdo certo.

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

Você pode tornar sua vida mais fácil, encapsulando o seu getter e lógica setter em uma classe base e, em seguida, simplesmente chamando esses métodos de quaisquer novas propriedades que você criar (simplesmente agindo como wrapper fino em torno desses métodos). Aqui está um exemplo:

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

}

... Desta forma, há muito pouca lógica em suas propriedades e você está repetindo menos código. Isso pressupõe as seguintes classes (que eu ridicularizados como genericized):

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

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

Isso não faz sentido. usando propertys a maneira que você tem atualmente eles, você pode simplesmente escrever:

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

Se você alterou a maneira que você quer você tem que especificar o parâmetro bem

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

tudo o que você poderia fazer é fazer uma "PropertyBag" emulador

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

Você acessar esta assim:

   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];    
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top