2012-12-23 19 views
5

Cho một lớp như thế này:Có thể nhận các giá trị tham số tùy chọn từ một hàm tạo bằng cách sử dụng sự phản chiếu không?

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; 
     } 
    } 

Có thể sử dụng phản ánh để có được giá trị mặc định của tham số tùy chọn không?

Trả lời

6

Cho phép lấy một chương trình cơ bản:

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

Và nhìn vào một số mã IL.

Đối 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 

Đối với chi tiết:

.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 

ý rằng chính đã 5 hardcoded như là một phần của cuộc gọi, và trong Foo. Phương thức gọi thực sự là mã hóa cứng giá trị không bắt buộc! Giá trị nằm ở cả trang web gọi và trang web callee.

Bạn sẽ có thể có được ở các giá trị tùy chọn bằng cách sử dụng các hình thức:

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

On MSDN cho DefaultValue (được đề cập trong câu trả lời khác):

Khách sạn này là chỉ được sử dụng trong ngữ cảnh thực thi. Trong bối cảnh chỉ phản chiếu, sử dụng thuộc tính RawDefaultValue thay thế. MSDN

Và cuối cùng là một 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

+0

lol - sửa lỗi typo trong hàm tạo ... được sao chép từ ví dụ khác ' d được sử dụng trên SO; O – BlueChippy

+0

Điều đó sẽ tạo sự khác biệt. Trong trường hợp đó, bạn sẽ muốn sử dụng [type] .GetConstructor() thay vì GetMethod(). –

+0

Đã cập nhật câu trả lời cho tài khoản cho sự khác biệt. Bạn có thể thay đổi từ 1 đến 2 để nhận giá trị tùy chọn thứ ba. Tôi đã thử nghiệm điều này và nó hoạt động trên máy tính của tôi, và DefaultValue [thay vì RawDefaultValue] cũng sẽ hoạt động tùy theo ngữ cảnh của sự phản chiếu. –

1

DefaultValue của lớp ParameterInfo là những gì bạn đang tìm kiếm:

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

Object tài liệu tham khảo không được đặt để một thể hiện của một đối tượng. – BlueChippy

+0

Thực ra trong bài đăng đầu tiên của bạn, bạn đã tham chiếu đến một số phương thức AbstractClassToTestSomeClass, trong khi trong phiên bản đã chỉnh sửa, hàm tạo của nó có tham số tùy chọn, hãy kiểm tra chỉnh sửa ở trên –

Các vấn đề liên quan