将字段值分配给泛型类型

本文关键字:泛型类型 分配 字段 | 更新日期: 2023-09-27 18:02:10

我有一个泛型方法,它将接受泛型类型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()时所做的事情),然后将实际值分配给结构体的字段,我知道将会在那里。如何将字段分配给通用对象?

将字段值分配给泛型类型

下面的代码将遍历原始结构体中的所有字段,如果存在于新的目标结构体实例中,将对它们进行映射。

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方法改变一个结构体(多亏了这个答案)。如果你想以这种方式从一个实例复制到另一个实例,你真的应该使用带有公共属性的类。