C#:如何在父类方法中获取子类传入的动态命名参数?
在C#父类方法中获取子类调用时的命名参数名称与值
你需要在父类Base的Get方法中,获取子类(如User、Task)调用该方法时传入的命名参数名称和对应值,尝试过params dynamic[] values但只能拿到值,无法获取参数名,以下是几种可行的实现方案:
方案1:使用匿名类型+反射
利用匿名类型的属性名与调用时的命名参数名一致的特性,结合反射提取参数名和对应值,调用语法最接近你的原始需求:
class Base { public dynamic Get(object parameters) { if (parameters == null) return null; // 构建参数名-值的字典 var paramDict = new Dictionary<string, dynamic>(); foreach (var prop in parameters.GetType().GetProperties()) { paramDict[prop.Name] = prop.GetValue(parameters); } // 这里可以直接使用paramDict处理参数 foreach (var kvp in paramDict) { Console.WriteLine($"{kvp.Key}: {kvp.Value}"); } return null; // 根据业务需求返回对应内容 } } class User : Base { public int Id { get; set; } public string Name { get; set; } public string Password { get; set; } public void Init() { // 调用时仅需给参数套上new {} this.Get(new { Id = 5, Name = "admin", Password = "admin" }); } } class Task : Base { public int Id { get; set; } public string Name { get; set; } public void Init() { this.Get(new { Id = 1, Name = "task1" }); } }
方案2:直接传递Dictionary<string, dynamic>
跳过反射,直接用字典传递键值对,性能更优,适合对性能敏感的场景:
class Base { public dynamic Get(Dictionary<string, dynamic> parameters) { if (parameters == null) return null; // 直接使用字典中的参数名和值 foreach (var kvp in parameters) { Console.WriteLine($"{kvp.Key}: {kvp.Value}"); } return null; } } class User : Base { public int Id { get; set; } public string Name { get; set; } public string Password { get; set; } public void Init() { this.Get(new Dictionary<string, dynamic> { { "Id", 5 }, { "Name", "admin" }, { "Password", "admin" } }); } }
方案3:C# 10+ 使用CallerArgumentExpression(适合固定少量参数)
利用C# 10引入的CallerArgumentExpression属性自动获取参数名,但需要为不同参数数量编写重载,扩展性有限:
using System.Runtime.CompilerServices; class Base { // 单个参数的版本 public dynamic Get<T>(T value, [CallerArgumentExpression("value")] string paramName = "") { Console.WriteLine($"{paramName}: {value}"); return null; } // 两个参数的版本 public dynamic Get<T1, T2>(T1 value1, T2 value2, [CallerArgumentExpression("value1")] string paramName1 = "", [CallerArgumentExpression("value2")] string paramName2 = "") { Console.WriteLine($"{paramName1}: {value1}"); Console.WriteLine($"{paramName2}: {value2}"); return null; } } class Task : Base { public int Id { get; set; } public string Name { get; set; } public void Init() { this.Get(Id = 1, Name = "task1"); } }
方案对比
- 匿名类型+反射:调用语法简洁直观,接近原始需求,但依赖反射,性能略低,适合大多数业务场景。
- Dictionary传参:无反射开销,性能更优,但调用时需要手动构建键值对,写法稍繁琐。
- CallerArgumentExpression:无需反射,但需要为不同参数数量编写重载,扩展性差,仅适合参数数量固定的场景。
为什么params dynamic[]无法获取参数名
params dynamic[]本质是将传入的参数打包成数组,而命名参数只是编译阶段的语法提示,编译后参数名称不会被保留到数组中,因此无法通过这种方式获取参数名。
内容的提问来源于stack exchange,提问作者zohaib yousaf
相关产品推荐
相关产品推荐

