装饰器模式下C#无法检测未使用方法,求解决方案
问题背景
在使用依赖注入容器注册装饰器模式时,代码结构如下:
public interface IFoo { string Print(); } public class Foo : IFoo { public string Print() => "Foo"; } public class Decorator(IFoo decorated) : IFoo { public string Print() { return "=" + decorated.Print() + "="; } } IServiceCollection services; services.AddTransient<IFoo, Foo>() .Decorate<Foo, Decorator>();
当移除某方法/类的最后一处业务调用后,静态代码分析工具会将装饰器中的调用视为有效引用,无法识别该代码已处于未使用状态。需要让工具忽略装饰器中的引用,以便检测出仅被装饰但未实际使用的方法/类。
解决方案
1. ReSharper/Rider 工具配置
如果使用JetBrains的ReSharper或Rider,可直接通过工具设置忽略装饰器类的引用:
- 打开设置窗口,导航到
Code Inspection > Settings > Unused Symbols - 在
Symbols to ignore when checking for unused references列表中,添加装饰器类的完全限定名(比如YourNamespace.Decorator) - 保存设置后,工具会忽略来自该装饰器的所有引用,若被装饰类(如
Foo)无其他业务调用,将被正确标记为未使用。
2. 自定义特性标记装饰器依赖
通过自定义特性标记装饰器的构造函数参数,再配置分析工具识别该特性以忽略对应引用:
// 自定义特性,标记装饰器的依赖参数 [AttributeUsage(AttributeTargets.Parameter)] public class DecoratorDependencyAttribute : Attribute { } // 修改装饰器构造函数,给依赖参数添加特性 public class Decorator([DecoratorDependency] IFoo decorated) : IFoo { public string Print() { return "=" + decorated.Print() + "="; } }
后续可通过Roslyn自定义分析器,设置规则:当符号的所有引用均来自带有DecoratorDependency特性的参数调用时,标记为未使用。
3. 编写自定义Roslyn分析器
若需要更精准的控制,可编写自定义Roslyn分析器实现逻辑:
- 遍历代码中所有引用,区分装饰器类的引用与业务代码的引用
- 当类/方法的所有引用均来自装饰器时,标记为未使用
该方案灵活性最高,但需要具备Roslyn开发基础。
4. 条件化DI注册(辅助方案)
在运行时层面通过条件判断控制DI注册,避免无效的装饰器绑定,但无法解决静态分析的未使用标记问题,仅作辅助:
// 假设通过静态分析或其他方式检测Foo是否被业务代码引用 bool isFooUsed = CheckFooUsage(); if (isFooUsed) { services.AddTransient<IFoo, Foo>() .Decorate<Foo, Decorator>(); }
目前C#标准库中没有内置特性可直接忽略装饰器的引用,主要依赖工具配置或自定义分析器实现需求。
内容的提问来源于stack exchange,提问作者Tomas Kubes
相关产品推荐
相关产品推荐

