繁体   English   中英

在C#中深度克隆一个深层对象(非常深)

[英]Deep cloning a deep object in C# (very deep)

我正在用Antlr4和C#编写玩具语言。 现在,我正在尝试编写一个类系统。 但是一个大问题使我的工作停了下来。 当我尝试克隆用户创建的类的实例时,其中的所有内容均引用原始类。 我的“班级”代码在这里

[Serializable]
public class Class : ICloneable
{
    public string ID;
    public ClassDef ClassContent = new ClassDef();

    public Helper ErrorHandler = new Helper();

    public Class()
    {
        ID = "";
    }
    public Class(string id)
    {
        ID = id;
    }

    public void Create(MainGrammarParser.ClassblockContext block)
    {
        ClassDef def = new ClassDef();
        def.Visit(block);
        ClassContent = def;
    }

    public object Clone()
    {
        Class clone = new Class(ID);
        clone.ClassContent = ClassContent.DeepClone();
        return clone;
    }
}

和“ ClassDef”的代码

public class ClassDef : SuperClass, ICloneable
{
    public override bool VisitClassStatFunctionDef([NotNull] MainGrammarParser.ClassStatFunctionDefContext context)
    {
        FunctionDefParser fd = GetFunctionDefParser();
        fd.Visit(context.functiondef());
        return true;
    }

    public override bool VisitClassStatElementDef([NotNull] MainGrammarParser.ClassStatElementDefContext context)
    {
        string id = context.classelem().ID().GetText();
        if (IsVarExists(id) || IsFunctionExists(id) || IsClassExists(id))
        {
            ErrorHandler.DuplicateError("[ELEMENT] '" + id  + "'");
        }
        ExpParser exp = GetExpParser();
        VarObject v = new VarObject(id);
        v.Value = exp.Visit(context.classelem().exp());
        Variables.Add(v);
        return true;
    }
}

和超类代码

public class SuperClass : MainGrammarBaseVisitor<bool>, ICloneable
{
    public VarCollection Variables = new VarCollection();
    public FunctionCollection Functions = new FunctionCollection();
    public ClassCollection Classes = new ClassCollection();

    public Helper ErrorHandler = new Helper();

    public VarObject GetVar(string id)
    {
        if (!IsVarExists(id))
        {
            ErrorHandler.NotFoundError("[DEFINITION] '" + id + "'");
        }
        return Variables.Find(id);
    }

    public Function GetFunction(string id)
    {
        if (!IsFunctionExists(id))
        {
            ErrorHandler.NotFoundError("[METHOD] '" + id + "'");
        }
        return Functions.Find(id);
    }

    public Class GetClass(string id)
    {
        if (!IsClassExists(id))
        {
            ErrorHandler.NotFoundError("[CLASS] '" + id + "'");
        }
        return Classes.Find(id);
    }

    public bool IsVarExists(string id)
    {
        if (!Variables.Contains(id)) { return false; }
        return true;
    }

    public bool IsFunctionExists(string id)
    {
        if (!Functions.Contains(id)) { return false; }
        return true;
    }

    public bool IsClassExists(string id)
    {
        if (!Classes.Contains(id)) { return false; }
        return true;
    }

    public ExpParser GetExpParser()
    {
        ExpParser output = new ExpParser();
        output.Parent = this;
        return output;
    }

    public EqualityParser GetEqualityParser()
    {
        EqualityParser output = new EqualityParser();
        output.Parent = this;
        return output;
    }

    public FunctionDefParser GetFunctionDefParser()
    {
        FunctionDefParser output = new FunctionDefParser();
        output.Parent = this;
        return output;
    }

    public IfParser GetIfParser()
    {
        IfParser output = new IfParser();
        output.Parent = this;
        return output;
    }

    public object Clone()
    {
        SuperClass output = new SuperClass();
        output.Variables = Variables.DeepClone();
        output.Functions = Functions.DeepClone();
        output.Classes = Classes.DeepClone();
        return output;
    }

    public SuperClass()
    { }
}

我自己编写了VarCollection,FunctionCollection和ClassCollection,它们只是具有find和exist方法的列表。 当我用我的语言尝试这样的代码时

class abc
{
    this a = "a"
    this b = "b"
    this c = "c"
    void abc(){}
}
newabc1 = new abc()
newabc1.a = 10
new1a = newabc1.a
newabc2 = new abc()
new2a = newabc2.a

“ new1a”和new2a都设置为10。我尝试了大多数技术,包括:反射,序列化,JsonSerialization,ICloneable,MemberWiseClone ...

在序列化中,我需要将[Serializable]应用于每个类,包括Antlr4自动生成的类。 因此,当我更新语法时,我需要再次放置它们。

在Json序列化(NewtonJson)中,序列化进入无限循环(Serializator警告我有关自引用循环,并且我禁用了循环错误)。

反射,IClonable,MemberWiseClone,这些都无法正常工作。 他们在内存中引用相同的地址,所以我得到相同的错误。

有什么帮助吗?

您可以使用序列化来深克隆对象,但请记住,您必须进行以下设置:

ReferenceLoopHandling = ReferenceLoopHandling.Ignore

到序列化程序,以防止进入无限循环。 如果您正在使用Newtonsoft,但是许多序列化程序都存在类似的ReferenceLoopHandling设置选项。

我解决了这个问题,但实际上不是:)我将字典实例用作类(例如在JavaScript中)。 当与Antlr一起使用时,在NewtonJson中创建序列化的对象是无效的,因为巨大的源代码会使序列化非常慢(大约2-3秒)。 这是我解决问题的方法。 有谁知道解析器生成器或创建语言的出色教程,这是我标记此答案之前的最后一个问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM