0

我正在尝试实现一种在我的应用程序中克隆元素的方法。这些元素是我定制和设计的(到目前为止,它们并没有那么复杂)。每个项目都被称为属性Children,其中列出了更多实例(将其想象为具有多个子分支的树视图)。

我有一个名为“环境”的对象,其中包含对所有这些孩子的引用。把它想象成一个拥有我所有树木的果园。当我想复制所有内容时,我希望能够在我的“环境”类上调用“克隆”并让它给我所有内容的副本。

这一切都工作了一段时间,但经过一些更改和代码重构后,它似乎不再工作了,我不知道为什么。我可以很好地跟踪堆栈跟踪,但在这种情况下这是不可能的。这是我的错误的屏幕截图。

在此处输入图像描述

我还将使用序列化将我的“环境”实际保存到文件中。然而,在我能做到这一点之前,我必须让序列化工作。

无论如何,我已经分别检查了我的单个树/分支/肢体对象,它们都成功克隆。我似乎唯一无法克隆的是“环境”类(我的果园)。这是我的“环境”类的来源:

Imports gE.gEngine
Imports LuaInterface
Imports gE.gEngine.Generic
Imports Microsoft.Xna.Framework
Imports System.Runtime.Serialization
Imports System.IO
Imports System.Runtime.Serialization.Formatters.Binary
Imports gE.gEngine.WorldObjects
Imports System.Windows.Forms
Imports Microsoft.Xna.Framework.Input
Imports System.Threading.Tasks
Imports System.Threading

<Serializable()> _
Public Class Environment

    Public World As WorldServices.World
    Public Players As WorldServices.Players
    Public Lighting As WorldServices.Lighting
    Public Environment As WorldServices.Environment
    Public GenericsLibrary As WorldServices.GenericsLibrary

    <NonSerialized()> _
    Public Lua As New LuaInterface.Lua
    <NonSerialized()> _
    Public SafetyContext As CommonEnum.SafetyContext = CommonEnum.SafetyContext.Safe

    Public Event EnvironmentChanged(ByVal sender As Object, ByVal e As GenericEventArgument)

    Public Sub call_EnvironmentChanged(ByVal sender As Object, ByVal e As GenericEventArgument)
        RaiseEvent EnvironmentChanged(sender, e)
    End Sub

    Public Sub New()
        GlobalShare.Environment = Me
        InitializeLua()

        Lighting = New WorldServices.Lighting()
        World = New WorldServices.World()
        Players = New WorldServices.Players()
        Environment = New WorldServices.Environment()
        GenericsLibrary = New WorldServices.GenericsLibrary()

        Dim ConstraintesGroup As New WorldObjects.Group With {
            .Name = "Constraintes",
            .Parent = GenericsLibrary
        }

        Dim ordsc As List(Of gEngine.WorldObjects.Lua) = Environment.GetScripts()
        ordsc.Sort(Function(x, y) x.RunIndex.CompareTo(y.RunIndex))
        For Each script As gEngine.WorldObjects.Lua In ordsc
            GlobalShare.Environment.RunScript(script.Source, script.Name)
        Next
    End Sub

    Public Sub SetSafetyContext(ByVal e As CommonEnum.SafetyContext)
        If e <> CommonEnum.SafetyContext.Unlocked Then
            SafetyContext = e
            Exit Sub
        End If
        Throw New Exception("Attempt to unlock safety context from unsafe Lua script!")
    End Sub

    Public Sub InitializeLua()
        Lua("Game") = GlobalShare.Game
        Lua("__Environment") = Me
        Lua("gel") = New gELua(Me)
        Lua.RegisterFunction("Print", Lua("gel"), Lua("gel").GetType().GetMethod("Print"))
        Lua.RegisterFunction("print", Lua("gel"), Lua("gel").GetType().GetMethod("Print"))
        Lua.RegisterFunction("SetSafetyContext", Lua("gel"), Me.GetType().GetMethod("SetSafetyContext"))

        Lua("Vector2") = New Lua_.Lua_Vector2
        Lua("Vector3") = New Lua_.Lua_Vector3
        Lua("Mouse") = New Lua_.Lua_Mouse

        Lua.NewTable("Helpers")
        Lua("Helpers.EnumHelper") = New Helpers.EnumHelper

        Dim GameTimer As New Stopwatch
        Lua("Time") = GameTimer
        GameTimer.Start()

        Lua.NewTable("__X")
    End Sub

    Public Function Clone() As Environment
        If [Object].ReferenceEquals(Me, Nothing) Then
            Return Nothing
        End If

        Dim formatter As IFormatter = New BinaryFormatter()
        Dim stream As IO.Stream = New MemoryStream()
        Using stream
            formatter.Serialize(stream, Me)
            stream.Seek(0, SeekOrigin.Begin)
            Return DirectCast(formatter.Deserialize(stream), [Environment])
        End Using
    End Function

    Public Sub RunScript(ByVal scr As String, ByVal name As String)
        Try
            Lua.DoString(scr, name)
        Catch ex As Exception
            Game.CallLogEvent(Me, New GenericEventArgument("LogEvent", "Error", ex.Message))
        End Try
    End Sub

End Class

代码有点乱,因为我并没有因为这个特定问题而对这个特定的类感到非常困惑(我想知道为什么在我继续改变它之前它不会序列化 - 我不想造成任何同时还有更多问题)。

根据错误,它似乎正在尝试序列化我的应用程序窗口(StudioWindow),但是,我在我的应用程序中找不到对它的任何引用。

所以我并不是真的要求你们为我找到参考(据我所知,它可能隐藏在我项目的其他部分深处),但我很想找到一种方法来缩小问题的范围。我一直在评论部分并试图消除我项目的某些部分作为问题,但这有点困难,因为如果没有其他部分运行,我的应用程序的某些方面将无法运行。

任何帮助表示赞赏。如果您想了解更多信息,请询问。我可能会得到你想要的任何信息。我的代码主要是 VB.NET(尽管它是一个混合项目,所以许多其他部分都在 C# 中),因此非常感谢任何 .NET 示例/解决方案/帮助并且同样有帮助(我可以阅读两者,所以不要犹豫)。

4

1 回答 1

2

您有不同的选项来防止订阅者的序列化。他们每个人都有优点或缺点。根据您的架构和需求:

  1. 使用事件的属性。对于事件,需要一个额外的 “字段”。在 C# 中:[字段:NonSerialized]。

  2. 将事件设置为 null,以在序列化之前删除所有订阅。

  3. 有时将所有数据保存在自己的元素中是一个很好的解决方案。保持这个数据对象本身非常简单且易于序列化。如果您采用这种方式,则不必关心您不想序列化的所有字段和委托

  4. 实现 ISerializable

于 2012-09-18T06:51:05.937 回答