2016-08-13 149 views
0

我正在用Antlr4和C#編寫玩具語言。現在我正在嘗試寫一個類系統。但是一個大問題阻止了我所有的工作。當我嘗試克隆用戶創建的類的實例時,其中的所有內容都引用原始類。我的 '類' 的代碼是在這裏在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和exists方法列出。 當我在語言

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)中,序列化進入一個無限循環(序列化器警告我關於自我引用循環和我禁用循環錯誤)。

反射,IClonable,MemberWiseClone,這些都沒有正常工作。他們在內存引用相同的地址,所以我得到相同的錯誤。

任何幫助?

回答

0

我解決了這個問題,但不是真的:)我使用字典實例作爲類(就像在JavaScript中)。在使用Antlr時,在NewtonJson中創建序列化對象是不合適的,因爲巨大的源代碼會使序列化非常慢(abt 2-3s)。這是我解決問題的方法。有沒有人知道一個解析器生成器或一個偉大的教程來創建語言,這是我最後一個問題,然後我標記這個答案。

0

您可以使用序列化到深克隆對象,但是請記住,你必須設置:

ReferenceLoopHandling = ReferenceLoopHandling.Ignore 

你的串行,以防止無限循環的進入。這是如果您正在使用Newtonsoft,但許多序列化程序存在類似的ReferenceLoopHandling setting選項。

+0

剛試過(再次),進入了無限循環:(代碼:JsonSerializerSettings設置=新JsonSerializerSettings(); settings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; 串序列化= JsonConvert.SerializeObject(來源設置); 回報( T)JsonConvert.DeserializeObject(序列化,設置); –

+0

@YahyaGedik您是怎麼使用它的,以及您使用的是哪個版本的Newtonsoft? – meJustAndrew

+0

昨天剛剛從它的網站下載了9.0.1。大多數問題來自Antlr4自動生成的文件。因爲他們是非常複雜和自我引用(?)。 –