显式实现接口的 ReSharper 文件布局

Posted

技术标签:

【中文标题】显式实现接口的 ReSharper 文件布局【英文标题】:ReSharper File Layout for explicit implemented interfaces 【发布时间】:2020-03-04 08:06:54 【问题描述】:

我正在尝试以这样一种方式配置 ReSharper 的文件布局,即格式化代码确实遵守“StyleCop SA1202”规则。

更多信息请参见https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1202.md。

基本上,这条规则表示元素的顺序必须匹配给定的模式。 首先是“公共”,然后是“内部”...

当我有一个实现显式接口的类时,它实际上是“公共的”。 见以下代码:

void IDisposable.Dispose()

    // Implementation

当我使用以下配置配置 ReSharper 文件布局时:

<Entry DisplayName="Methods">
    <Entry.Match>
        <Kind Is="Method" />
    </Entry.Match>
    <Entry.SortBy>
        <Access Order="Public Internal Protected" />
    </Entry.SortBy>
</Entry>

显式实现的接口放在任何公共方法之后。

有没有办法配置 ReSharper 的文件布局,以便在使用显式接口实现时遵守规则 SA1202?

亲切的问候

【问题讨论】:

【参考方案1】:

我正在使用 StyleCop 文件布局,并在最后添加了一条 Dispose 方法的特殊规则:

<?xml version="1.0" encoding="utf-16"?>
<Patterns
    xmlns="urn:schemas-jetbrains-com:member-reordering-patterns">
    <TypePattern DisplayName="Non-reorderable types">
        <TypePattern.Match>
            <Or>
                <And>
                    <Kind Is="Interface" />
                    <Or>
                        <HasAttribute Name="System.Runtime.InteropServices.InterfaceTypeAttribute" />
                        <HasAttribute Name="System.Runtime.InteropServices.ComImport" />
                    </Or>
                </And>
                <Kind Is="Struct" />
                <HasAttribute Name="JetBrains.Annotations.NoReorderAttribute" />
                <HasAttribute Name="JetBrains.Annotations.NoReorder" />
            </Or>
        </TypePattern.Match>
    </TypePattern>
    <TypePattern DisplayName="xUnit.net Test Classes" RemoveRegions="All">
        <TypePattern.Match>
            <And>
                <Kind Is="Class" />
                <HasMember>
                    <And>
                        <Kind Is="Method" />
                        <HasAttribute Name="Xunit.FactAttribute" Inherited="True" />
                    </And>
                </HasMember>
            </And>
        </TypePattern.Match>
        <Entry DisplayName="Setup/Teardown Methods">
            <Entry.Match>
                <Or>
                    <Kind Is="Constructor" />
                    <And>
                        <Kind Is="Method" />
                        <ImplementsInterface Name="System.IDisposable" />
                    </And>
                </Or>
            </Entry.Match>
            <Entry.SortBy>
                <Kind Order="Constructor" />
            </Entry.SortBy>
        </Entry>
        <Entry DisplayName="All other members" />
        <Entry DisplayName="Test Methods" Priority="100">
            <Entry.Match>
                <And>
                    <Kind Is="Method" />
                    <HasAttribute Name="Xunit.FactAttribute" />
                </And>
            </Entry.Match>
            <Entry.SortBy>
                <Name />
            </Entry.SortBy>
        </Entry>
    </TypePattern>
    <TypePattern DisplayName="NUnit Test Fixtures" RemoveRegions="All">
        <TypePattern.Match>
            <And>
                <Kind Is="Class" />
                <HasAttribute Name="NUnit.Framework.TestFixtureAttribute" Inherited="True" />
            </And>
        </TypePattern.Match>
        <Entry DisplayName="Setup/Teardown Methods">
            <Entry.Match>
                <And>
                    <Kind Is="Method" />
                    <Or>
                        <HasAttribute Name="NUnit.Framework.SetUpAttribute" Inherited="True" />
                        <HasAttribute Name="NUnit.Framework.TearDownAttribute" Inherited="True" />
                        <HasAttribute Name="NUnit.Framework.FixtureSetUpAttribute" Inherited="True" />
                        <HasAttribute Name="NUnit.Framework.FixtureTearDownAttribute" Inherited="True" />
                    </Or>
                </And>
            </Entry.Match>
        </Entry>
        <Entry DisplayName="All other members" />
        <Entry DisplayName="Test Methods" Priority="100">
            <Entry.Match>
                <And>
                    <Kind Is="Method" />
                    <HasAttribute Name="NUnit.Framework.TestAttribute" />
                </And>
            </Entry.Match>
            <Entry.SortBy>
                <Name />
            </Entry.SortBy>
        </Entry>
    </TypePattern>
    <TypePattern DisplayName="StyleCop Classes, Interfaces, &amp; Structs" RemoveRegions="All">
        <TypePattern.Match>
            <Or>
                <Kind Is="Class" />
                <Kind Is="Struct" />
                <Kind Is="Interface" />
            </Or>
        </TypePattern.Match>
        <Entry DisplayName="Constants">
            <Entry.Match>
                <Kind Is="Constant" />
            </Entry.Match>
            <Entry.SortBy>
                <Access Order="Public Internal ProtectedInternal Protected Private" />
                <Static />
                <Readonly />
            </Entry.SortBy>
        </Entry>
        <Entry DisplayName="Fields">
            <Entry.Match>
                <Kind Is="Field" />
            </Entry.Match>
            <Entry.SortBy>
                <Access Order="Public Internal ProtectedInternal Protected Private" />
                <Static />
                <Readonly />
            </Entry.SortBy>
        </Entry>
        <Entry DisplayName="Constructors">
            <Entry.Match>
                <Kind Is="Constructor" />
            </Entry.Match>
            <Entry.SortBy>
                <Access Order="Public Internal ProtectedInternal Protected Private" />
                <Static />
                <Readonly />
            </Entry.SortBy>
        </Entry>
        <Entry DisplayName="Destructors">
            <Entry.Match>
                <Kind Is="Destructor" />
            </Entry.Match>
            <Entry.SortBy>
                <Access Order="Public Internal ProtectedInternal Protected Private" />
                <Static />
                <Readonly />
            </Entry.SortBy>
        </Entry>
        <Entry DisplayName="Delegates">
            <Entry.Match>
                <Kind Is="Delegate" />
            </Entry.Match>
            <Entry.SortBy>
                <Access Order="Public Internal ProtectedInternal Protected Private" />
                <Static />
                <Readonly />
            </Entry.SortBy>
        </Entry>
        <Entry DisplayName="Events">
            <Entry.Match>
                <Kind Is="Event" />
            </Entry.Match>
            <Entry.SortBy>
                <Access Order="Public Internal ProtectedInternal Protected Private" />
                <Static />
                <Readonly />
            </Entry.SortBy>
        </Entry>
        <Entry DisplayName="Enums">
            <Entry.Match>
                <Kind Is="Enum" />
            </Entry.Match>
            <Entry.SortBy>
                <Access Order="Public Internal ProtectedInternal Protected Private" />
                <Static />
                <Readonly />
            </Entry.SortBy>
        </Entry>
        <Entry DisplayName="Interfaces">
            <Entry.Match>
                <Kind Is="Interface" />
            </Entry.Match>
            <Entry.SortBy>
                <Access Order="Public Internal ProtectedInternal Protected Private" />
                <Static />
                <Readonly />
            </Entry.SortBy>
        </Entry>
        <Entry DisplayName="Properties">
            <Entry.Match>
                <Kind Is="Property" />
            </Entry.Match>
            <Entry.SortBy>
                <Access Order="Public Internal ProtectedInternal Protected Private" />
                <Static />
                <Readonly />
            </Entry.SortBy>
        </Entry>
        <Entry DisplayName="Indexers">
            <Entry.Match>
                <Kind Is="Indexer" />
            </Entry.Match>
            <Entry.SortBy>
                <Access Order="Public Internal ProtectedInternal Protected Private" />
                <Static />
                <Readonly />
            </Entry.SortBy>
        </Entry>
        <Entry DisplayName="Methods">
            <Entry.Match>
                <Kind Is="Method" />
            </Entry.Match>
            <Entry.SortBy>
                <Access Order="Public Internal ProtectedInternal Protected Private" />
                <Static />
                <Readonly />
            </Entry.SortBy>
        </Entry>
        <Entry DisplayName="Structs">
            <Entry.Match>
                <Kind Is="Struct" />
            </Entry.Match>
            <Entry.SortBy>
                <Access Order="Public Internal ProtectedInternal Protected Private" />
                <Static />
                <Readonly />
            </Entry.SortBy>
        </Entry>
        <Entry DisplayName="Classes">
            <Entry.Match>
                <Kind Is="Class" />
            </Entry.Match>
            <Entry.SortBy>
                <Access Order="Public Internal ProtectedInternal Protected Private" />
                <Static />
                <Readonly />
            </Entry.SortBy>
        </Entry>
        <Entry DisplayName="Dispose">
            <Entry.Match>
                <Name Is="Dispose" />
            </Entry.Match>
            <Entry.SortBy>
                <Access Order="Public Internal ProtectedInternal Protected Private" />
                <Static />
                <Readonly />
            </Entry.SortBy>
        </Entry>
    </TypePattern>
</Patterns>

【讨论】:

【参考方案2】:

您可以创建一个新区域,在其中捕获私有属性并实现接口,并在接口名称中使用正则表达式“I.*”

<Region Name="Explicit interface implementation">
  <Entry DisplayName="Interface properties">
    <Entry.Match>
      <And>
        <Kind Is="Property" />
        <ImplementsInterface Name="I.*" />
        <Access Is="Private" />
      </And>
    </Entry.Match>
  </Entry>
</Region>

【讨论】:

以上是关于显式实现接口的 ReSharper 文件布局的主要内容,如果未能解决你的问题,请参考以下文章

尽管有ReSharper [NotNull]注释,我应该添加显式空值检查吗?

有没有办法将 ReSharper 代码清理设置应用于 .scss (SASS) 文件?

ReSharper 和隐式类型变量

为啥接口的显式实现不能公开?

Resharper 所说的“对象分配(明显)”是啥意思?

Resharper 自定义模式变量