2015-07-10 81 views
0

我有一個通用的方法,它將接受泛型類型T.我知道在運行時,T將是我之前定義的一組結構中的某種類型的結構。我無法弄清楚如何實例化結構並初始化結構體的字段。將字段值分配到泛型

public void mymethod<T>() { 
    // T is a struct which I know will have certain fields. 
    // I want to initialize them in this method 
    Type type = typeof(T); 
    System.Reflection.MemberInfo attributes = typeof(T); 
    //which line is correct, top one or one below? 
    //System.Reflection.MemberInfo attributes = typeof(T).GetMember("length", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance)[0]; 
} 

我是否需要爲每個我知道會出現的字段分配一個MemberInfo對象?或者是否有可能獲得傳入的結構體中的所有字段(因爲我知道不同的結構體將具有某些其他字段不同的字段)。另外,一旦我有一個字段,我該如何爲它指定一個特定結構的值?

只是爲了使問題更清楚:我想要完成的是以下內容。我確信在運行時,my_method將接受來自我在不同類中定義的一組結構的某種結構。下面是對這些結構的2個例子:

public struct Struct1 { 
    public int length; 
    public int width; 
} 

public struct Struct2 { 
    public int length; 
    public int width; 
    public int height; 
    public string color; 
} 

的MyMethod()將接受一個通用的結構作爲T.我想根據我的計算中的MyMethod做(這是不相關的,所以我的避風港分配給該結構域這裏沒有顯示他們)。每個結構都有一些基本字段(比如上面的例子中,Struct1和Struct2都有長度和寬度,但Struct2有更多的屬性)。對於任何以T形式傳入的結構體,我想爲其字段賦值。因此,舉例來說,如果Struct2在與T通過,那麼我想說

struct2.length = 1; 
struct2.width = 2; 
struct2.height; 
struct2.color; 

我需要找到做上述的一般等價物,所以我嘗試使用的MemberInfo實現這一目標。我的問題是我如何至少分配任何結構體的基本字段?我知道如果我說Struct2 struct2 = new Struct2(),那麼所有的屬性是initalized,但我不能說typeof(T) somestruct = new typeof(T)所以,我需要初始化MemberInfo對象的每個可能或不在那裏的字段?我不認爲這會起作用,因爲不同的結構會有不同的領域。如果有辦法獲得結構的所有字段,將它們初始化爲一些基本的值(比如當您說Struct2 struct2 = new Struct2()時做了什麼),然後將實際值分配給結構我知道會在那裏。如何將字段分配給通用對象?

+0

我認爲這個問題提供了你的答案:http://stackoverflow.com/questions/2974519/generic-constraints-where-t-struct-and-where-t-class – GinjaNinja

+0

好吧,這將允許我訪問所有屬性。但現在我該如何初始化它們。例如,我知道在一個結構中會有一個屬性「length」。如果我知道長度是定義的第二個屬性,我可以說「屬性[1] = 1」嗎? –

+0

由於您沒有告訴我們關於您嘗試解決的實際問題的任何信息,因此很難看到您要在此完成的工作。你不能「初始化一個類型」,除非你的意思是實例化它,或者可能爲它的一個「靜態」成員賦值。總之,我們需要更多地瞭解你實際想要完成的事情。 –

回答

0

以下內容將迭代您的原始結構中的所有字段,並且如果出現在新的目標結構實例中,它們將映射它們。

void Main() 
{ 
    var instance = MyMethod<Struct1, Struct2>(new Struct1() { length = 1, width = 2}); 
} 

public TTo MyMethod<TFrom, TTo>(TFrom fromStruct) 
{ 
    var toType = typeof(TTo); 
    var instance = Activator.CreateInstance<TTo>(); 

    foreach (var fromField in fromStruct.GetType().GetFields()) 
    { 
     var toField = instance.GetType().GetField(
      fromField.Name, BindingFlags.Public | BindingFlags.Instance); 

     if (toField != null) 
     { 
      var value = fromField.GetValue(fromStruct); 
      TypedReference reference = __makeref(instance); 
      toField.SetValueDirect(reference, value); 
     } 
    } 

    return instance; 
} 

現在說,雖然這工作你不應該這樣做!這是通過未記錄的__makeref方法對結構進行變異(感謝this answer)。如果你想以這種方式從一個實例複製到另一個實例,你應該使用具有公共屬性的類。