是否可以使用reflection从构造函数中获取可选参数值?

鉴于这样的类:

public abstract class SomeClass { private string _name; private int _someInt; private int _anotherInt; public SomeClass(string name, int someInt = 10, int anotherInt = 20) { _name = name; _someInt = someInt; _anotherInt = anotherInt; } } 

是否可以使用reflection来获取可选参数的默认值?

让我们采取一个基本的计划:

 class Program { static void Main(string[] args) { Foo(); } public static void Foo(int i = 5) { Console.WriteLine("hi" +i); } } 

并查看一些IL代码。

对于Foo:

 .method public hidebysig static void Foo([opt] int32 i) cil managed { .param [1] = int32(0x00000005) // Code size 24 (0x18) .maxstack 8 IL_0000: nop IL_0001: ldstr "hi" IL_0006: ldarg.0 IL_0007: box [mscorlib]System.Int32 IL_000c: call string [mscorlib]System.String::Concat(object, object) IL_0011: call void [mscorlib]System.Console::WriteLine(string) IL_0016: nop IL_0017: ret } // end of method Program::Foo 

主要:

 .method private hidebysig static void Main(string[] args) cil managed { .entrypoint // Code size 9 (0x9) .maxstack 8 IL_0000: nop IL_0001: ldc.i4.5 IL_0002: call void ConsoleApplication3.Program::Foo(int32) IL_0007: nop IL_0008: ret } // end of method Program::Main 

请注意,main有5个硬编码作为调用的一部分,在Foo中 。 调用方法实际上是硬编码可选的值! 该值位于呼叫站点和被叫站点。

您可以使用以下表单获取可选值:

typeof(SomeClass).GetConstructor(new []{typeof(string),typeof(int),typeof(int)}) .GetParameters()[1].RawDefaultValue

在MSDN上的DefaultValue(在另一个答案中提到):

此属性仅在执行上下文中使用。 在仅reflection上下文中,请改用RawDefaultValue属性。 MSDN

最后一个POC:

 static void Main(string[] args) { var optionalParameterInformation = typeof(SomeClass).GetConstructor(new[] { typeof(string), typeof(int), typeof(int) }) .GetParameters().Select(p => new {p.Name, OptionalValue = p.RawDefaultValue}); foreach (var p in optionalParameterInformation) Console.WriteLine(p.Name+":"+p.OptionalValue); Console.ReadKey(); } 

http://bartdesmet.net/blogs/bart/archive/2008/10/31/c-4-0-feature-focus-part-1-optional-parameters.aspx

您正在寻找ParameterInfo类的DefaultValue

 var defaultValues = typeof(SomeClass).GetConstructors()[0].GetParameters().Select(t => t.DefaultValue).ToList();