将字段值分配给泛型类型

时间:2015-07-10 14:07:21

标签: c# generics struct

我有一个接受泛型类型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将接受我在另一个类中定义的一组结构中的某种结构。以下是其中两个结构的示例:

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()那么所有的属性都被初始化了但我真的不能说typeof(T) somestruct = new typeof(T)那么,我是否需要为每个可能与否的字段初始化MemberInfo对象在那儿?我不认为这会有效,因为不同的结构会有不同的领域。如果有一种方法可以获取结构的所有字段,将它们初始化为某个基本值(例如当您说Struct2 struct2 = new Struct2()时所执行的操作),然后将实际值分配给结构我知道会在那里。如何将字段分配给通用对象?

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)。如果你想以这种方式从一个实例复制到另一个实例,你真的应该使用具有公共属性的类。