“拡張”することは可能ですか?プロパティ“ class&#8221 ;?

StackOverflow https://stackoverflow.com/questions/1410916

  •  05-07-2019
  •  | 
  •  

質問

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

これを作成するアイデアや、コードをよりクリーンにする別のアイデアがありますか? ありがとう

ギヨーム

役に立ちましたか?

解決

C#または.NET自体の内部でこれを行う機能はありませんが、これらの多くを行う場合は、ポストシャープ。基本的に、コンパイル時に追加のコードを挿入する属性を定義できます。入力するコードは次のようになります。

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

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

また、コンパイル時に、PostSharpはプロパティを新しいLocalizedPropertyAttributeクラスで定義したテンプレートに置き換えます。

他のヒント

説明したほど簡潔に することはできませんが、セッターの複雑さと冗長性を減らすことができます。

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

単一のインデックス付きプロパティを実装し、好みに応じて次の2つの構文の選択肢のいずれかを提供できます。コードは基本的に、具体的に名前が付けられたリソースを受け入れ、適切なコンテンツを返す関数になります。

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

ゲッターロジックとセッターロジックを基本クラスにカプセル化し、作成した新しいプロパティからこれらのメソッドを呼び出すだけで、生活が楽になります(単にメソッドの薄いラッパーとして機能します)。次に例を示します。

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

それは意味がありません。 現在のプロパティをそのまま使用して、次のように書くことができます。

   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帰属
所属していません StackOverflow
scroll top