我正在尝试实现一种在我的应用程序中克隆元素的方法。这些元素是我自定义和设计的(到目前为止,它们并不是那么复杂)。每个项目都称为Children
属性,其中列出了更多实例(将其视为具有多个子分支的树视图)。
我有一个名为“环境”的对象,其中包含对所有这些孩子的引用。把它想象成一个拥有我所有树木的果园。当我想要复制所有内容时,我希望能够在我的“环境”类中调用“clone”并让它为我提供所有内容的副本。
这一切都工作了一段时间,但经过一些更改和代码重构后,它似乎不再起作用,我不知道为什么。我可以很好地遵循堆栈跟踪,但在这种情况下,这是不可能的。这是我的错误的屏幕截图。
我还将使用序列化将我的“环境”实际保存到文件中。然而,在我能够做到这一点之前,我必须将序列化作为一般工作。
无论如何,我已经单独检查了我的单个树/分支/肢体对象,它们都成功克隆了。我似乎无法克隆的唯一东西是“环境”类(我的果园)。这是我的“环境”类的来源:
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示例/解决方案/帮助都非常受欢迎,同样有用(我可以阅读这两个,所以不要犹豫)。
答案 0 :(得分:2)
您可以使用不同的选项来阻止订阅者的序列化。它们中的每一个都有优点或缺点。根据您的架构和您的需求:
使用事件的属性。对于活动,还需要额外的“字段”。在C#中:[field:NonSerialized]。
将事件设置为null,以在序列化之前删除所有订阅。
有时将所有数据保存在自己的元素中是一个很好的解决方案。保持此数据对象本身非常简单,易于序列化。如果您这样做,您不必关心所有字段和代表您不想序列化
实施ISerializable