2009-02-23 70 views
40

Tôi đã viết một lớp bằng python mà tôi muốn kết hợp thành một assembly .net qua IronPython và khởi tạo trong ứng dụng C#. Tôi đã chuyển lớp sang IronPython, đã tạo một thư viện và tham chiếu nó. Bây giờ, làm thế nào để tôi thực sự có được một thể hiện của lớp đó?Khởi tạo lớp python trong C#

Các chàng lớp (một phần) như thế này:

class PokerCard: 
    "A card for playing poker, immutable and unique." 

    def __init__(self, cardName): 

stub thử nghiệm tôi đã viết trong C# là:

using System; 

namespace pokerapp 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      var card = new PokerCard(); // I also tried new PokerCard("Ah") 
      Console.WriteLine(card.ToString()); 
      Console.ReadLine(); 
     } 
    } 
} 

gì làm tôi phải làm để nhanh chóng lớp này trong C# ?

Trả lời

51

Lớp IronPython là không Lớp .NET. Chúng là các cá thể của IronPython.Runtime.Types.PythonType, đây là lớp metaclass của Python. Điều này là do các lớp Python là động và hỗ trợ bổ sung và loại bỏ các phương thức trong thời gian chạy, những thứ bạn không thể làm với các lớp .NET.

Để sử dụng các lớp Python trong C#, bạn sẽ cần phải sử dụng lớp ObjectOperations. Lớp này cho phép bạn hoạt động trên các kiểu trăn và các cá thể trong ngữ nghĩa của chính ngôn ngữ đó. ví dụ. nó sử dụng các phương pháp ma thuật khi thích hợp, tự động quảng bá các số nguyên đến độ dài, vv Bạn có thể tìm hiểu thêm về ObjectOperations bằng cách nhìn vào nguồn hoặc sử dụng phản xạ.

Đây là một ví dụ. Calculator.py chứa một lớp đơn giản:

class Calculator(object): 
    def add(self, a, b): 
     return a + b 

Bạn có thể sử dụng nó từ trước NET 4.0 mã của bạn C# như thế này:

ScriptEngine engine = Python.CreateEngine(); 
ScriptSource source = engine.CreateScriptSourceFromFile("Calculator.py"); 
ScriptScope scope = engine.CreateScope(); 

ObjectOperations op = engine.Operations; 

source.Execute(scope); // class object created 
object klaz = scope.GetVariable("Calculator"); // get the class object 
object instance = op.Call(klaz); // create the instance 
object method = op.GetMember(instance, "add"); // get a method 
int result = (int)op.Call(method, 4, 5); // call method and get result (9) 

Bạn sẽ cần phải tham khảo các hội IronPython.dll, Microsoft. Scripting và Microsoft.Scripting.Core.

C# 4 làm việc này dễ dàng hơn nhiều với loại động mới mới.

ScriptEngine engine = Python.CreateEngine(); 
ScriptSource source = engine.CreateScriptSourceFromFile("Calculator.py"); 
ScriptScope scope = engine.CreateScope(); 
source.Execute(scope); 

dynamic Calculator = scope.GetVariable("Calculator"); 
dynamic calc = Calculator(); 
int result = calc.add(4, 5); 

Nếu bạn đang sử dụng Visual Studio 2010 trở lên với NuGet, chỉ cần thực hiện thao tác này để tải xuống và tham khảo thư viện thích hợp.

Install-Package IronPython 
+1

tôi không có đại diện để chỉnh sửa , nhưng trong mẫu Calculator.py, dấu "def" đầu tiên sẽ được thụt vào. Ví dụ tuyệt vời, mặc dù! Rất hữu ích. Bây giờ .Net 4.0 đã hết, sẽ rất tuyệt khi thấy một ví dụ được cập nhật. –

+5

Đã thêm ví dụ .Net 4.0, sử dụng cùng một lớp mẫu Máy tính của bạn. –

+0

Cảm ơn, tôi đã thêm thụt lề. –

-4

Tôi đã tìm kiếm cao và thấp và tôi sợ rằng dường như không có nhiều thông tin liên quan đến điều này. Tôi khá chắc chắn rằng không ai nghĩ ra cách để làm điều này theo cách mà bạn muốn.

Lý do chính tôi cho rằng đây là vấn đề là để xem loại PokerCard trong ứng dụng C# của bạn, bạn sẽ phải biên dịch mã Python của bạn thành IL. Tôi không tin rằng có bất kỳ Python -> IL trình biên dịch ra khỏi đó.

31

Hiện tại .Net 4.0 được phát hành và có loại động, ví dụ này nên được cập nhật. Sử dụng file python giống như trong câu trả lời ban đầu m-sắc nét của:

class Calculator(object): 
    def add(self, a, b): 
     return a + b 

Đây là cách bạn sẽ gọi nó là sử dụng Net 4.0:

string scriptPath = "Calculator.py"; 
ScriptEngine engine = Python.CreateEngine(); 
engine.SetSearchPaths(new string[] {"Path to your lib's here. EG:", "C:\\Program Files (x86)\\IronPython 2.7.1\\Lib"}); 
ScriptSource source = engine.CreateScriptSourceFromFile(scriptPath); 
ScriptScope scope = engine.CreateScope(); 
ObjectOperations op = engine.Operations; 
source.Execute(scope); 

dynamic Calculator = scope.GetVariable("Calculator"); 
dynamic calc = Calculator(); 
return calc.add(x,y);   

Một lần nữa, bạn cần phải thêm tham chiếu đến IronPython.dll và Microsoft.Scripting.

Như bạn thấy, thiết lập ban đầu và tạo tệp nguồn giống nhau.

Nhưng khi nguồn được thực thi thành công, làm việc với các hàm python dễ dàng hơn rất nhiều nhờ từ khóa "động" mới.

+0

Cảm ơn bạn đã thêm ví dụ! –

+0

Điều này thực sự đã giúp! –

0

Tôi đang cập nhật ví dụ trên do Clever Human cung cấp cho các lớp IronPython được biên dịch (dll) thay vì mã nguồn IronPython trong tệp .py.

# Compile IronPython calculator class to a dll 
clr.CompileModules("calculator.dll", "calculator.py") 

C# 4.0 mã với các loại động mới như sau:

// IRONPYTHONPATH environment variable is not required. Core ironpython dll paths should be part of operating system path. 
ScriptEngine pyEngine = Python.CreateEngine(); 
Assembly myclass = Assembly.LoadFile(Path.GetFullPath("calculator.dll")); 
pyEngine.Runtime.LoadAssembly(myclass); 
ScriptScope pyScope = pyEngine.Runtime.ImportModule("calculator"); 
dynamic Calculator = pyScope.GetVariable("Calculator"); 
dynamic calc = Calculator(); 
int result = calc.add(4, 5); 

Tài liệu tham khảo:

  1. Using Compiled Python Classes from .NET/CSharp IP 2.6
  2. Static Compilation of IronPython scripts
Các vấn đề liên quan