2015-07-28 61 views
1

我正在尋找一種方法來做任意類實例以及屬性指派和可能的方法調用在.Net和最好的C#。由於任意太寬泛的一個詞讓我告訴你我在做什麼。.net仲裁運行時類實例和方法調用

比方說,我有一個DLL(objects.dll),包含:

public class Person 
{ 
    // Field 
    public string name; 

    // Constructor that takes no arguments. 
    public Person() 
    { 
     name = "unknown"; 
    } 

    // Constructor that takes one argument. 
    public Person(string nm) 
    { 
     name = nm; 
    } 

    // Method 
    public void SetName(string newName) 
    { 
     name = newName; 
    } 

} 

public class Table 
{ 
    // Field 
    public int width; 
    public int lenth; 
    public int height; 

    // Constructor that takes no arguments. 
    public Table() 
    { 
     width = 0; 
     length = 0; 
     height = 0 
    } 

    // Constructor that takes three arguments. 
    public Table(int w, int l, int h) 
    { 
     width = w; 
     length = l; 
     height = h; 
    } 

    // Method 
    public void SetWLH(int w, int l, int h) 
    { 
     width = w; 
     length = l; 
     height = h; 
    } 
} 

public class Printer 
{ 
    public Printer(){} 

    public void printAPerson(Person p) 
    { 
     //do stuff with p 
    } 

    public void printATable(Table t) 
    { 
     // do stuff with t 
    } 
} 

我希望能夠實例以上任一類,設置屬性值和調用方法在運行時從不同的程序在最通用的可能。例如。可以說,我哈默爾一個PROGRAMM稱爲MYPROG.EXE,我希望能夠做到以下幾點

MYPROG.EXE objects.dll人名測試名打印機printAPerson 其中:

  • objects.dll是包含所有必需的類

  • 人是我第一次將實例名的dll是它的屬性

  • 測試名是我將分配給此屬性的值

  • 打印機是我將使用用於打印

  • printAPerson類是在打印機I類需要與指定對象作爲參數來調用該方法。

正如你所看到的,在我的使用情況最好的情況下,無論是對象和類是/將在編譯時是已知的,所以我想應該非鑄造成爲可能。如果這是不可能的,我會盡我所能。

我已經看到了這個,How to use reflection to call a method and pass parameters whose types are unknown at compile time?,這對我有限的知識類型做我想要的減去鑄造位或我可能會被誤認爲。

非常感謝!

+0

您鏈接的問題對我的問題有所有答案。你對這篇文章有什麼不瞭解? – Juan

+0

我在最後一句「減去鑄造位」中解釋它。該文特別要求ClassA aa = new ClassA();在開始時實例化。如果我可以逃避,我會更喜歡它。 – Zach

回答

0

對於您的可執行輸入格式,您是否靈活?如果是這樣,你可以通過約定來做你想做的事情。我會使用JSON結構這樣一個做到這一點:

{ 
    Command : "", 
    Arguments : { 
     Argument1 : 0, 
     Argument2 : { }, // can be another complex object 
     Argument3 : [] // an empty array maybe ... 
    } 
} 

where命令會是這樣的「ClassName.MethodName」,參數將是一個JSON對象,每個對象屬性表示你的方法參數。

在您的可執行文件中,您必須使用庫(示例http://www.newtonsoft.com/json)解析此JSON,並使用反射來反序列化每個JSON對象參數並調用您的方法。如果你不能工作,請告訴我,我會嘗試做一個例子(如果我有時間,今天晚上,因爲我現在正在工作)。

對於你的情況,你只是想打印一個Person類型的對象到打印機的權利?你可以執行下面的命令:

{ 
    Command : "Printer.PrintAPerson", 
    Arguments : { 
    p : { name : 'george' } 
    } 
} 

如果你想依靠一個標準的協議,請檢查JSON-RPC協議:http://json-rpc.org/wiki/specification

0

而不是使用反射,你可以使用dynamic。但是這需要改變Printer類和其他類。你會失去intellisense和編譯時間檢查。

public class Printer 
{ 
    public Printer() { } 

    public void printAPerson(dynamic p) 
    { 
     //do stuff with p 
     Console.WriteLine("Person name: " + p.name); 
    } 

    public void printATable(dynamic t) 
    { 
     // do stuff with t 
     Console.WriteLine("printATable(Table p) is called"); 
    } 
} 

public class TestDynamic 
{ 
    public static void Test() 
    { 
     // To get the type by name, 
     // the full type name (namespace + type name) is needed 
     Type personType = Type.GetType("StackOverflowCodes.Person"); 
     object personObj = Activator.CreateInstance(personType); 

     // Implicit cast to dynamic 
     dynamic person = personObj; 
     person.SetName("Alan Turing"); 

     Type printerType = Type.GetType("StackOverflowCodes.Printer"); 
     object printerObj = Activator.CreateInstance(printerType); 

     dynamic printer = printerObj; 
     printer.printAPerson(personObj); 
    } 
} 
+0

非常感謝Muraad。在這一點上,我並不在意intellisense在編譯時檢查。然而在你的例子中,你特別要求person.SetName(「Alan Turing」);和printer.printAPerson(personObj);在我的使用案例中我負擔不起。再次感謝很多。 – Zach

+0

然後可能沒有辦法反思。但是您也需要知道類型名稱和方法名稱。否則將不得不僅僅根據方法簽名來搜索類型和方法。 「遍歷所有類型在加載的程序集中迭代當前類型的所有MethodInfos。如果方法需要一個Person並返回void,那麼您已經找到了(可能)正確的方法和類型。但是你必須先找到Person類型......如果不知道類型/方法的名稱或其他類型的約定,這可能會變得非常多毛和昂貴。問候和祝你好運! –