2012-06-06 26 views
5

Theo dõi trên excellent answer này, tôi tự hỏi liệu DLR có sử dụng từ khóa dynamic có thể cho phép cách viết mã ít hơn đối với cụm được tạo ra không.Sử dụng DLR để chạy mã được tạo bằng CompileAssemblyFromSource?

Ví dụ, có thể mã câu trả lời nói trên của:

using (Microsoft.CSharp.CSharpCodeProvider foo = 
      new Microsoft.CSharp.CSharpCodeProvider()) 
{ 
    var res = foo.CompileAssemblyFromSource(
     new System.CodeDom.Compiler.CompilerParameters() { 
      GenerateInMemory = true 
     }, 
     "public class FooClass { public string Execute() { return \"output!\";}}" 
    ); 

    var type = res.CompiledAssembly.GetType("FooClass"); 
    var obj = Activator.CreateInstance(type); 
    var output = type.GetMethod("Execute").Invoke(obj, new object[] { }); 
} 

trở thành một cái gì đó như:

using (Microsoft.CSharp.CSharpCodeProvider foo = 
      new Microsoft.CSharp.CSharpCodeProvider()) 
{ 
    var res = foo.CompileAssemblyFromSource(
     new System.CodeDom.Compiler.CompilerParameters() { 
      GenerateInMemory = true 
     }, 
     "public class FooClass { public string Execute() { return \"output!\";}}" 
    ); 

    var type = res.CompiledAssembly.GetType("FooClass"); 
    dynamic obj = Activator.CreateDynamicInstance(type); 
    var output = obj.Execute(); 
} 
+1

Có, có ít mã hơn một chút. Làm cho nó hoạt động bằng cách sử dụng 'Activator.CreateInstance()' thay thế. Tôi không thấy câu hỏi nào khác. –

+1

Có, tôi đã thử nó và nhận ra rằng nó "chỉ hoạt động" với 'dynamic' thay vì' var'. Những thứ tuyệt vời. –

Trả lời

7

Có, bạn có thể làm điều đó và nó hoạt động tốt. Tuy nhiên, trong khi sử dụng từ khóa động là thuận tiện hơn, nó sử dụng cuối ràng buộc và vẫn chỉ là không an toàn, theo nghĩa đó, như một cách rõ ràng bằng cách sử dụng sự phản ánh. Nếu thiết kế của bạn cho phép nó, nó thậm chí còn tốt hơn để sử dụng một giao diện chia sẻ hoặc lớp cơ sở để kết nối sớm. Bạn có thể làm điều này bằng cách tạo một kiểu công khai trong assembly của bạn hoặc trong một assembly thứ ba, được chia sẻ, và sau đó thêm một tham chiếu đến assembly đó từ assembly mới mà bạn đang biên dịch động. Sau đó, trong mã được tạo, bạn có thể kế thừa từ loại được chia sẻ đó trong hội đồng được tham chiếu. Ví dụ, tạo ra một giao diện:

public interface IFoo 
{ 
    string Execute(); 
} 

Sau đó tự động biên dịch lắp ráp như thế này:

using (Microsoft.CSharp.CSharpCodeProvider foo = new Microsoft.CSharp.CSharpCodeProvider()) 
{ 
    var params = new System.CodeDom.Compiler.CompilerParameters(); 
    params.GenerateInMemory = true; 

    // Add the reference to the current assembly which defines IFoo 
    params.ReferencedAssemblies.Add(Assembly.GetExecutingAssembly().Location); 

    // Implement the IFoo interface in the dynamic code 
    var res = foo.CompileAssemblyFromSource(params, "public class FooClass : IFoo { public string Execute() { return \"output!\";}}"); 
    var type = res.CompiledAssembly.GetType("FooClass"); 

    // Cast the created object to IFoo 
    IFoo obj = (IFoo)Activator.CreateInstance(type); 

    // Use the object through the IFoo interface 
    obj.Execute(); 
} 

Tùy thuộc vào bao nhiêu điều khiển bạn có hơn mã năng động, điều này có thể hoặc không thể thực hiện, nhưng khi nó được, nó là tốt đẹp để có thời gian biên dịch-loại kiểm tra. Ví dụ, nếu bạn đã cố gắng để thực hiện:

IFoo obj = (IFoo)Activator.CreateInstance(type); 
obj.Execcute(); 

Đó dòng thứ hai sẽ ngay lập tức thất bại trong việc biên dịch bởi vì nó đánh vần sai, trong khi với các từ khoá động hoặc phản chiếu, dòng đó sẽ biên dịch thành công nhưng nó sẽ gây ra một thời gian chạy ngoại lệ. Ví dụ: sau đây sẽ không gặp lỗi biên dịch thời gian:

dynamic obj = Activator.CreateDynamicInstance(type); 
obj.Execcute(); 
+0

cảm ơn cho câu trả lời phức tạp (+1), nhưng tôi phải không đồng ý với tuyên bố của bạn "trong khi nó là thuận tiện hơn để làm điều đó theo cách đó, không phải là loại là an toàn". Lỗi ràng buộc có thể xảy ra vì an toàn loại được đảm bảo. Câu lệnh của bạn sẽ đúng với kịch bản ngược lại, nơi không có lỗi liên kết nào xảy ra khi cần. –

+0

Tôi không chắc chắn ý bạn là gì, nhưng tôi đã sửa đổi câu trả lời của mình để làm cho nó rõ ràng hơn. –

+0

Tôi tin rằng tôi khá rõ ràng bằng cách nói rằng bạn đã sai khi nói rằng cách tiếp cận này không an toàn. –

0

Đó là một trong những tình huống mà các DLR được thiết kế cho. Bạn có thể sử dụng nó theo cách đó để gọi các thành viên của một loại động được nạp trong khi tránh tất cả việc gõ thêm từ cách thủ công gọi .GetMethod().Invoke().

+0

Làm thế nào, chính xác? . . . –

+0

Chính xác như câu hỏi hiển thị trong ví dụ của nó. Lưu ý sự khác biệt giữa hai dòng cuối cùng trong mỗi dòng. –

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