C# 代理类能否包含对原始类的引用

C# 代理类能否包含对原始类的引用,c#,serialization,unity3d,protocol-buffers,protobuf-net,C#,Serialization,Unity3d,Protocol Buffers,Protobuf Net,我正在尝试为名为Transform的第三方类创建代理。我只需要序列化它的几个公共成员,包括对另一个此类类实例的一些引用,并公开转换的内部列表。因此,我为它编写了代理,但我不确定是否可以在代理的字段上定义[ProtoMember]属性,这些字段属于Transform类型。或者应该是转换代理?现在我的代码是: [ProtoContract(AsReferenceDefault = true)] public class TransformSurrogate { [ProtoMember(1)

我正在尝试为名为
Transform
的第三方类创建代理。我只需要序列化它的几个公共成员,包括对另一个此类类实例的一些引用,并公开
转换的内部列表。因此,我为它编写了代理,但我不确定是否可以在代理的字段上定义
[ProtoMember]
属性,这些字段属于
Transform
类型。或者应该是
转换代理
?现在我的代码是:

[ProtoContract(AsReferenceDefault = true)]
public class TransformSurrogate {
    [ProtoMember(1)]
    Vector3 localPosition { get; set; }
    [ProtoMember(2)]
    Vector3 localScale { get; set; }
    [ProtoMember(3)]
    Quaternion localRotation { get; set; }
    [ProtoMember(4, AsReference = true)]
    Transform parent { get; set; }
    [ProtoMember(5, AsReference = true)]
    List<Transform> children { get; set; }

    public static explicit operator TransformSurrogate(Transform transform) {
        if (transform == null) return null;
        var surrogate = new TransformSurrogate();
        surrogate.localPosition = transform.localPosition;
        surrogate.localRotation = transform.localRotation;
        surrogate.localScale = transform.localScale;
        surrogate.parent = transform.parent;
        surrogate.children = new List<Transform>();
        for (int i = 0; i < transform.childCount; ++i) {
            surrogate.children.Add(transform.GetChild(i));
        }
        return surrogate;
    }

    public static explicit operator Transform(TransformSurrogate surrogate) {
        if (surrogate == null) return null;
        var transform = new GameObject().transform;
        transform.localPosition = surrogate.localPosition;
        transform.localRotation = surrogate.localRotation;
        transform.localScale = surrogate.localScale;
        transform.parent = (Transform) surrogate.parent;
        foreach (var child in surrogate.children) {
            child.parent = transform;
        }
        return transform;
    }
}

然而,我在反序列化过程中遇到了一个错误,告诉我Protobuf无法在类之间转换。我认为这是因为在代理类中混合了原始类,但我不确定。

对于某些数据类型,是的,它会起作用,我现在正在做完全相同的事情(为Unity3D变换编写代理)。早些时候,我在一个代理上进行了测试。下面是代码如何开始

[ProtoContract(AsReferenceDefault = true)]
    [ProtoSurrogate(typeof(Mesh))]
    sealed class MeshSurrogate {
        [ProtoMember(1)]
        Matrix4x4[] bindposes;

        [ProtoMember(2)]
        BoneWeight[] boneWeights;

/* Lots more follows */
(ProtoSurrogateAttribute是自定义的…它可以实现您可能期望的功能) 它可以很好地序列化和反序列化所有数据类型的原始非代理类型字段

不过,转换变得更有趣。这里有一个潜在的问题——据报道,引用不能很好地处理代理——太糟糕了,因为这是我们Unity序列化策略的核心

我会更新,如果我得到这个工作

更新: 事实证明,这相当复杂

我得到的解决方案是,基本上任何继承UnityEngine.Object的东西都会得到一个代理项,该代理项包含3个且仅包含3个成员—instanceIdBeforeSerialization(通过UnityEngine.Object.GetInstanceID()获得)、一个“shell”和一个“数据”。只有在序列化过程中第一次遇到此代理时,才会填充shell和数据,否则为null。Shell负责实例化对象,并在[OnDeserialized]方法中填充每个对象的数据。当shell创建一个对象时,它会将其存储在一个表中,该表具有从旧实例id到新实例id的映射,因此当任何代理项转换为原始类型时,它只需要在表中搜索它的新对象。因为shell在流中放置得更早,所以至少在对象图中需要引用它们之前,所有对象都已初始化

不幸的是,我无法让数据类直接存储对Unity对象的引用,但这是一个库,因此最大的方便是用户,而不是作者

现在这些问题都解决了,看来这种方法将很好地发挥作用。我会看看我的雇主是否允许它进入资产商店

更新:
这将在资产存储完成后进入。首先要添加很多代理,因此可能需要一段时间。

在依赖于非核心类型的复杂类型的上下文中,这很难回答;你有没有一个例子来说明仅仅使用简单的局部类型的问题?@MarcGravel现在我正试图在更简单的环境中模拟这种情况,但是如果你想知道什么是Vector3和四元数类型,你可以跳过它们,因为它们是简单的结构,我成功地序列化了它们。我现在主要关注的是Transform类。变换是Unity3D内置类型(如果有帮助的话)。
[ProtoContract(AsReferenceDefault = true)]
    [ProtoSurrogate(typeof(Mesh))]
    sealed class MeshSurrogate {
        [ProtoMember(1)]
        Matrix4x4[] bindposes;

        [ProtoMember(2)]
        BoneWeight[] boneWeights;

/* Lots more follows */