C# ReSharperを使用してタイプメンバーを並べ替える



クラスの構造、およびそのメンバーを配置する順序に関して、いくつかの規則があります。

ここでは、たとえば、StyleCopが使用するルール 、おそらくあなたの会社には独自のルールがあります。

構造を手動で維持することは非常に難しく、退屈で時間がかかります。特に、クラスにかなりの数のプロパティ、フィールド、メソッドなどがある場合はそうです。

この投稿では、ReSharperを使用してこのプロセスを自動化する方法について説明します。



問題



時には高速コーディングでは、メンバーの並べ替えを忘れて、このようなものが得られます。

おridge
public class DemoClass : IEquatable<DemoClass> { public string SecondProperty { get; set; } private bool fieldBool; public override int GetHashCode() { return base.GetHashCode(); } public string SomeProperty { get; set; } public void DoSomething() { } private string fieldString; public DemoClass(bool fieldBool, string fieldString) { this.fieldBool = fieldBool; this.fieldString = fieldString; } public static void DoSomethingStatic() { } public bool Equals(DemoClass other) { throw new NotImplementedException(); } }
      
      







デフォルトの並べ替え



しかし、幸いなことに、ReSharperにはコードクリーンアップツールがあります。 また、[ タイプメンバー並べ替え ]オプションをオンにして実行すると、順序付けされたメンバーを持つクラスが取得さます。

  public class DemoClass : IEquatable<DemoClass> { private bool fieldBool; private string fieldString; public DemoClass(bool fieldBool, string fieldString) { this.fieldBool = fieldBool; this.fieldString = fieldString; } public string SomeProperty { get; set; } public string SecondProperty { get; set; } public bool Equals(DemoClass other) { throw new NotImplementedException(); } public override int GetHashCode() { return base.GetHashCode(); } public void DoSomething() { } public static void DoSomethingStatic() { } }
      
      







カスタムルール



しかし、デフォルトのソートが私たちに合わず、標準として受け入れられているソートと異なる場合はどうでしょうか?

この場合、ReSharperではデフォルトのルールを上書きできます。

ReSharper->オプション->コード編集-> C#->メンバーレイアウトと入力し、カスタムレイアウトをオンにします。

ソート順を記述するXMLが表示されます。

 <Patterns xmlns="urn:shemas-jetbrains-com:member-reordering-patterns"> <Pattern> <!--static fields and constants--> <Entry> <Match> <Or Weight="100"> <Kind Is="constant"/> <And> <Kind Is="field"/> <Static/> </And> </Or> </Match> <Sort> <Kind Order="constant field"/> </Sort> </Entry> <Entry> ... </Entry> </Pattern> <Pattern> ... <Pattern> </Patterns>
      
      







パターン要素親要素は、その内部に多くのパターン要素を含むことができ、その要素はさらに多くのエントリ要素を含むことができます。

Entry要素は、いくつかのアクションを実行するレコードです。 パターン要素のエントリの順序は、要素の順序に影響します。

次の順序が必要だとします:コンストラクター、メソッド、他のメンバー。

これを行うには、次のようなルールを記述できます。

 <?xml version="1.0" encoding="utf-8"?> <Patterns xmlns="urn:shemas-jetbrains-com:member-reordering-patterns"> <Pattern> <Entry> <Match> <Kind Is="constructor" /> </Match> </Entry> <Entry> <Match> <Kind Is="method" /> </Match> </Entry> <Entry /> </Pattern> </Patterns>
      
      







各Entry要素には、探しているものを記述するネストされたMatch要素が含まれています。 検索のより詳細なルールを設定し、論理演算子Or、And、Notおよびオペランドを使用できます。

オペランド
<Kind Is = "..." /> Is属性には、クラス、構造体、インターフェイス、列挙型、デリゲート、型、コンストラクタ、デストラクタ、プロパティ、インデクサ、メソッド、演算子、フィールド、定数、イベント、メンバを指定できます
<Name Is = "..." [IgnoreCase = "true / false"] /> Is属性には正規表現を含めることができます
<HasAttribute CLRName = "..." [継承= "true / false"] /> CLRName属性には正規表現を含めることができます
<Access Is = "..." /> Is属性には、public、protected、internal、protected-internal、privateを指定できます
<静的/>
<要約/>
<Virtual />
<オーバーライド/>
<封印された/>
<読み取り専用/>
<ImplementsInterface CLRName = "..." /> CLRName属性には正規表現を含めることができます
<HandlesEvent />


また、各Entry要素にはSortを含めることができます。これは、同じEntry内で見つかったメンバーのソートに影響します。

たとえば、静的フィールドと定数を見つけて、クラスの最初に配置する必要があります。 また、名前で並べ替えます。 これを行うには、パターンの先頭に次のエントリを追加する必要があります。

  <Entry> <Match> <Or> <Kind Is="constant" /> <And> <Kind Is="field" /> <Static /> </And> </Or> </Match> <Sort> <Name /> </Sort> </Entry>
      
      







並べ替えは複数の値で行うことができます。次の例では、アクセスレベルと名前ですべてのメソッドを並べ替えます。

  <Entry> <Match> <Kind Is="method"/> </Match> <Sort> <Access Order="public internal protected-internal protected private" /> <Name/> </Sort> </Entry>
      
      







グルーピング



グループ化もサポートされています。

メソッドを静的とインスタンスに分け、名前でソートし、適切な領域にラップする必要があるとします。 これを行うには、グループの子を持つ2つの異なるEntry要素を作成する必要があります。

  <Entry> <Match> <And> <Kind Is="method" /> <Static/> </And> </Match> <Group Region="Static methods" /> </Entry> <Entry> <Match> <Kind Is="method" /> </Match> <Group Region="Instance methods" /> </Entry>
      
      







クラスが実装したインターフェイスのすべてのメンバーをインターフェイスの名前でソートし、このインターフェイスの名前で領域をラップする必要がある場合はどうでしょうか? これを行うには、次のようにします。

  <Entry> <Match> <Kind Is="member" /> <ImplementsInterface/> </Match> <Sort> <ImplementsInterface/> </Sort> <Group> <ImplementsInterface Region="${ImplementsInterface} Members" /> </Group> </Entry>
      
      







この例では、変数$ {ImplementsInterface}はインターフェイスの名前と等しくなります。

また、Pattern要素はRemoveAllRegions属性をサポートします。これは、trueまたはfalse(デフォルトではfalse)に設定できます。 trueに設定されている場合、グループ化する前に、それ以前のすべてのリージョンが削除されます。



重さ



条件(一致)が一度に複数のタイプを満たす場合はどうなりますか?

メソッドを除くすべてのプライベートメンバーを1つのリージョンにグループ化するとします。 次のルールを書くことができます。

  <Entry> <Match> <Access Is="private" /> </Match> <Group Region="Private members" /> </Entry> <Entry> <Match> <Kind Is="method" /> </Match> <Group Region="All methods" /> </Entry>
      
      







ただし、プライベートメソッドがある場合は、両方のルールに該当します。 最初のルールが以前に適用され、プライベートメソッドを除くすべてのメソッドが2番目のルールに該当します。 その結果、プライベートメンバーを含むリージョンにはプライベートメソッドも含まれます。

正常に実行されたオペランドごとに1つのデフォルトの重みポイントが与えられ、これらのポイントが合計されます。 この場合、各要素には、それぞれ<Access Is = "private" />および<Kind Is = "method" />の1つのオペランドがあります。 2番目のルールを実行する場合は、オペランドのWeight属性を使用できます。

  <Entry> <Match> <Access Is="private" /> </Match> <Group Region="Private members" /> </Entry> <Entry> <Match> <Kind Is="method" Weight="5"/> </Match> <Group Region="All methods" /> </Entry>
      
      







したがって、2番目のイベントはより重要になり、すべてが意図したとおりにグループ化されます。



パターン



最初に、Pattern要素について説明しました。Match要素を含めることもでき、この要素は、パターンを含むルールが動作する場所を決定します。

次に、すべてのインターフェースで別のソートが必要な状況を想像してみましょう。 このような状況では、別のパターン要素を作成できます。

  <Pattern> <Match> <Kind Is="interface" /> </Match> ... </Pattern>
      
      







指定されたパターンで記述されるすべてのルールは、インターフェースにのみ影響します。



おわりに



この投稿では、ReSharperの機能のいくつかを紹介し、おそらくあなたの人生を楽にします。

この投稿は、この問題に関する完全なドキュメントではありません。

ソース:






All Articles