能否不使用魔法字符串获取C#构造参数名称?(Ninject场景)
解决Ninject构造函数参数魔法字符串的问题
当然可以用nameof或者强类型表达式替代魔法字符串,彻底解决重构不友好的问题,以下是两种可行方案:
1. 直接使用nameof关键字
这是最简单直接的方案,把魔法字符串替换为nameof(构造函数参数名)即可。编译器会自动解析参数名称,重构时参数名修改后nameof会同步更新,不会出现字符串不匹配的问题。
假设你的MyService构造函数定义如下:
public class MyService { public MyService(IRuntimeDependency paramName) { // 构造函数逻辑 } }
修改后的实例获取代码:
var service = Kernel.Get<MyService>(new ConstructorArgument(nameof(paramName), runtimeInstance));
2. 强类型表达式树方案(更安全)
如果想要极致的类型安全,避免手动输入参数名,可以封装一个扩展方法,通过Lambda表达式提取构造函数参数名称,连nameof都无需手动编写:
封装扩展方法
public static class NinjectConstructorParamExtensions { public static ConstructorArgument ForParam<TService>(Expression<Func<TService, object>> parameterExpression) { var memberExpr = parameterExpression.Body as MemberExpression; // 处理值类型参数的装箱情况 if (memberExpr == null && parameterExpression.Body is UnaryExpression unaryExpr) { memberExpr = unaryExpr.Operand as MemberExpression; } if (memberExpr == null) { throw new ArgumentException("表达式必须指向构造函数的参数"); } return new ConstructorArgument(memberExpr.Member.Name, null); } // 链式设置参数值 public static ConstructorArgument WithValue(this ConstructorArgument arg, object value) { return new ConstructorArgument(arg.Name, value); } }
使用方式
var service = Kernel.Get<MyService>( NinjectConstructorParamExtensions.ForParam<MyService>(s => s.paramName) .WithValue(runtimeInstance) );
这种方式下,如果你重构修改了paramName的名称,Lambda表达式会直接编译报错,从根源上避免了参数名称不匹配的问题。
内容的提问来源于stack exchange,提问作者Tim Long
相关产品推荐
相关产品推荐

