【问题标题】:Assigning field values to generic type将字段值分配给泛型类型
【发布时间】:2015-07-10 14:07:21
【问题描述】:

我有一个接受泛型类型 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 中所做的计算将字段分配给该结构(这无关紧要,所以我没有在这里展示它们)。每个 struct 都有一些基本字段(如上例中,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() 时所做的),然后将实际值分配给结构的字段struct 我知道会在那里。如何将字段分配给通用对象?

【问题讨论】:

  • 我认为这个问题提供了你的答案:stackoverflow.com/questions/2974519/…
  • 好的,这样我就可以访问所有属性。但现在我该如何初始化它们。例如,我知道在结构中会有一个属性“长度”。如果我知道长度是定义的第二个属性,我可以说“attributes[1] = 1”吗?
  • 在这里很难看出你想要完成什么,因为你没有告诉我们你想要解决的实际问题。您不能“初始化类型”,除非您的意思是实例化它,或者可能对其static 成员之一进行分配。简而言之,我们需要更多地了解您实际想要完成的工作。
  • 请不要调用 attributes 在 C# 中称为 fields 的东西!

标签: c# generics struct


【解决方案1】:

以下内容将遍历原始结构中的所有字段,如果存在于新的目标结构实例中,则会映射它们。

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

【讨论】:

    猜你喜欢
    • 2021-10-22
    • 1970-01-01
    • 2022-12-08
    • 2018-05-06
    • 1970-01-01
    • 2020-06-12
    • 1970-01-01
    • 1970-01-01
    • 2022-10-18
    相关资源
    最近更新 更多