4

我有struct这样的

public struct InstrumentDefinition2
{
    public int instrumentId;
    public int Decimals;
    public long MinPriceIncrement_Mantissa;
    public short MinPriceIncrement_Exponent;
    public long RoundLot_Mantissa;
    public short RoundLot_Exponent;
    public char MsgType;        // 'd' - Security Definition 'f' - Security Status?
}

[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate void InstrumentReplayCallback(ref InstrumentDefinition2 value);

它通过委托调用从这个 c++ 结构构造:

typedef struct _InstrumentDefinition {
    int32_t instrumentId;
    int32_t Decimals;
    int64_t MinPriceIncrement_Mantissa;
    int16_t MinPriceIncrement_Exponent;
    int64_t RoundLot_Mantissa;
    int16_t RoundLot_Exponent;
    char MsgType;        // 'd' - Security Definition 'f' - Security Status
} InstrumentDefinition;

它工作正常。我不确定是否可以将 InstrumentDefinition2 声明为class. 但我喜欢声明InstrumentDefinition2struct,我认为它是关于“指向 C++ 内存块的指针”。

但是在处理过程中我需要将它复制到一个类中。所以我想声明非常相似C#的类:

public class InstrumentDefinition
{
    public int instrumentId;
    public int Decimals;
    public long MinPriceIncrement_Mantissa;
    public short MinPriceIncrement_Exponent;
    public long RoundLot_Mantissa;
    public short RoundLot_Exponent;
    public char MsgType;        // 'd' - Security Definition 'f' - Security Status?
}

问题是如何将InstrumentDefinition2结构复制到InstrumentDefinition类?当然,我可以一一分配所有字段,但它会:

  • 我想比较慢
  • 容易出错(如果引入了新字段而我忘记添加它的“应对”怎么办?)

那么我可以在不应对每个领域的情况下以某种方式做到这一点吗?

4

2 回答 2

3

如果要通过匹配名称来复制类实例的字段或属性值,可以使用以下代码段:

public void ShallowCopyValues<T1, T2>(T1 firstObject, T2 secondObject)
{
    const BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public;
    var firstFieldDefinitions = firstObject.GetType().GetFields(bindingFlags);
    IEnumerable<FieldInfo> secondFieldDefinitions = secondObject.GetType().GetFields(bindingFlags);

    foreach (var fieldDefinition in firstFieldDefinitions)
    {
        var matchingFieldDefinition = secondFieldDefinitions.FirstOrDefault(fd => fd.Name == fieldDefinition.Name &&
                                                                                  fd.FieldType == fieldDefinition.FieldType);
        if (matchingFieldDefinition == null)
            continue;

        var value = fieldDefinition.GetValue(firstObject);
        matchingFieldDefinition.SetValue(secondObject, value);
    }
}

此代码使用反射来确定具有相同名称和相同类型的字段。如果找到匹配项,则在第二个对象上更新该值。此外:这段代码比一个一个地赋值要慢,但这并不重要,因为通常类没有大量的字段,这几乎不会导致性能损失。

考虑此代码不完整。在生产代码中,我肯定会推荐一个像 Automapper ( https://github.com/AutoMapper/AutoMapper#readme ) 这样的库,它更加灵活和可配置,正如 simsim 所提到的。

此外,您可以使用相同的布局将 C# 类映射到 C++ 结构,如 Mathew Watson 所述。您只需将其应用于StructLayoutAttributeMSDN 上此示例中所示的类:http: //msdn.microsoft.com/en-us/library/795sy883.aspx重要的是 C# 中的类具有相同的内存布局正如您的结构在 C++ 中所具有的那样。

于 2013-06-12T09:41:25.413 回答
0

对于自动字段/属性值复制,我会使用AutomoapperValue injectioner或类似的东西。在您的情况下,使用值注入器复制值将如下所示:

instrumentDefinition.InjectFrom(instrumentDefinition2);

假设变量名称对应于类和结构名称。

于 2013-06-12T09:15:28.510 回答