xar*_*eth 6 .net c# random serialization
我正在尝试深度克隆包含System.Random变量的对象.我的应用程序必须是确定性的,因此我需要捕获随机对象状态.我的项目基于.Net Core 2.0.
我在这里使用了一些深度克隆代码(你如何在.NET(特别是C#)中对对象进行深度复制?)使用序列化.
System.Random的文档是混合的:
序列化
https://msdn.microsoft.com/en-us/library/system.random(v=vs.110).aspx
http://referencesource.microsoft.com/#mscorlib/system/random.cs,bb77e610694e64ca(源代码)
不可序列化
https://docs.microsoft.com/en-us/dotnet/api/system.random?view=netframework-4.7.1
https://docs.microsoft.com/en-us/dotnet/api/system.random?view=netcore-2.0
我收到以下错误.
System.Runtime.Serialization.SerializationException HResult = 0x8013150C Message =在程序集'System.Private.CoreLib中输入'System.Random',Version = 4.0.0.0,Culture = neutral,PublicKeyToken = 7cec85d7bea7798e'未标记为可序列化.来源= System.Runtime.Serialization.Formatters
System.Random可以按我想要的方式克隆吗?
我创建了一个小程序来说明.
using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
namespace RandomTest
{
class Program
{
static void Main(string[] args)
{
Container C = new Container();
Container CopyC = DeepClone(C);
}
public static T DeepClone<T>(T obj)
{
using(var ms = new MemoryStream())
{
var formatter = new BinaryFormatter();
formatter.Serialize(ms, obj); //<-- error here
ms.Position = 0;
return (T)formatter.Deserialize(ms);
}
}
}
[Serializable]
public class Container
{
public ObjectType AnObject;
public Container()
{
AnObject = new ObjectType();
}
}
[Serializable]
public class ObjectType
{
//[NonSerialized] // Uncommenting here removes the error
internal System.Random R;
}
}
Run Code Online (Sandbox Code Playgroud)
我可能不需要Container对象,但这个结构更像我的应用程序.
使R [NonSerialized]删除错误但在反序列化后我没有得到我的Random对象.我尝试重新创建随机对象,但它启动了一个新的随机序列,因此打破了确定性要求.
你可以用来JSON.NET做这个。
使用项目| 管理 NuGet 包以将“Newtonsoft.Json”(最新稳定版本 10.0.3)添加到您的项目中。
然后你可以编写一个Cloner使用 Json.NET 克隆对象的类:
public static class Cloner
{
public static T Clone<T>(T source)
{
if (ReferenceEquals(source, null))
return default(T);
var settings = new JsonSerializerSettings { ContractResolver = new ContractResolver() };
return JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(source, settings), settings);
}
class ContractResolver : DefaultContractResolver
{
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
{
var props = type.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
.Select(p => base.CreateProperty(p, memberSerialization))
.Union(type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
.Select(f => base.CreateProperty(f, memberSerialization)))
.ToList();
props.ForEach(p => { p.Writable = true; p.Readable = true; });
return props;
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后你可以编写一些代码,如下所示:
var inner = new ObjectType {R = new Random(12345)};
var outer = new Container {AnObject = inner};
var clone = Cloner.Clone(outer);
Console.WriteLine(clone.AnObject.R.Next()); // Prints 143337951
Console.WriteLine(outer.AnObject.R.Next()); // Also prints 143337951
Run Code Online (Sandbox Code Playgroud)