我试图确定使用以下序列化代理来启用匿名函数/委托/ lambdas的序列化可能导致什么问题.
// see http://msdn.microsoft.com/msdnmag/issues/02/09/net/#S3
class NonSerializableSurrogate : ISerializationSurrogate
{
public void GetObjectData(object obj, SerializationInfo info, StreamingContext context)
{
foreach (FieldInfo f in obj.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
info.AddValue(f.Name, f.GetValue(obj));
}
public object SetObjectData(object obj, SerializationInfo info, StreamingContext context,
ISurrogateSelector selector)
{
foreach (FieldInfo f in obj.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
f.SetValue(obj, info.GetValue(f.Name, f.FieldType));
return obj;
}
}
Run Code Online (Sandbox Code Playgroud)
清单1 改编自 Counting Demo
我可以想到的主要问题可能是一个问题是匿名类是内部编译器细节,并且它的结构不能保证在.NET Framework的修订版之间保持不变.我很确定这是基于我对迭代器的类似问题的研究.
我正在调查匿名函数的序列化.我期待这不起作用,但发现它确实在某些情况下.只要lambda没有&强制编译器生成匿名类,一切正常.
如果编译器需要生成的类来实现匿名函数,则抛出SerializationException.这是因为编译器生成的类未标记为可序列化.
namespace Example
{
[Serializable]
class Other
{
public int Value;
}
[Serializable] …
Run Code Online (Sandbox Code Playgroud) 如果在创建文件时出现问题,我一直在写一个临时文件,然后移动到目的地.就像是:
var destination = @"C:\foo\bar.txt";
var tempFile = Path.GetTempFileName();
using (var stream = File.OpenWrite(tempFile))
{
// write to file here here
}
string backupFile = null;
try
{
var dir = Path.GetDirectoryName(destination);
if (!Directory.Exists(dir))
{
Directory.CreateDirectory(dir);
Util.SetPermissions(dir);
}
if (File.Exists(destination))
{
backupFile = Path.Combine(Path.GetTempPath(), new Guid().ToString());
File.Move(destination, backupFile);
}
File.Move(tempFile, destination);
if (backupFile != null)
{
File.Delete(backupFile);
}
}
catch(IOException)
{
if(backupFile != null && !File.Exists(destination) && File.Exists(backupFile))
{
File.Move(backupFile, destination);
}
}
Run Code Online (Sandbox Code Playgroud)
问题是在这种情况下新的"bar.txt"不会从"C:\ foo"目录继承权限.然而,如果我直接在"C:\ foo"中通过explorer/notepad等创建文件,则没有问题,所以我相信权限在"C:\ foo"上正确设置.
找到移动文件夹时 …
GetMessages
使用Rx 编写函数的最简洁方法是什么:
static void Main()
{
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
var messages = GetMessages(socket, IPAddress.Loopback, 4000);
messages.Subscribe(x => Console.WriteLine(x));
Console.ReadKey();
}
static IObservable<string> GetMessages(Socket socket, IPAddress addr, int port)
{
var whenConnect = Observable.FromAsyncPattern<IPAddress, int>(socket.BeginConnect, socket.EndConnect)(addr, port);
// now will receive a stream of messages
// each message is prefixed with an 4 bytes/Int32 indicating it's length.
// the rest of the message is a string
// ????????????? Now What ?????????????
}
Run Code Online (Sandbox Code Playgroud)
一个简单的服务器作为上述示例的驱动程序:http://gist.github.com/452893#file_program.cs …
我希望这可以工作,但显然IL生成的方式,它抛出NullReferenceException
.为什么编译器不能为查询生成类似的代码?
在这种ThisWorks
情况下,编译器生成的代码短路表达式的其余部分,为什么它不能为LINQ查询案例做同样的事情?
class Target
{
public ChildTarget Child;
}
class ChildTarget
{
public int[] Values;
}
IEnumerable<int> ThisWorks(Target target) =>
target.Child?.Values.Select(x => x);
IEnumerable<int> ThisDoesNotWork(Target target) =>
from x in target.Child?.Values select x;
ThisWorks(new Target());
ThisDoesNotWork(new Target()); // this throws NullReferenceException
Run Code Online (Sandbox Code Playgroud)
反编译结果
private static IEnumerable<int> ThisDoesNotWork(Target target)
{
ChildTarget child = target.Child;
IEnumerable<int> values = (child != null) ? child.Values : null;
Func<int, int> func;
if ((func = Program._func) == null)
{
func = (Program._func = …
Run Code Online (Sandbox Code Playgroud) 我有一个看起来像的查询
SELECT
P.Column1,
P.Column2,
P.Column3,
...
(
SELECT
A.ColumnX,
A.ColumnY,
...
FROM
dbo.TableReturningFunc1(@StaticParam1, @StaticParam2) AS A
WHERE
A.Key = P.Key
FOR XML AUTO, TYPE
),
(
SELECT
B.ColumnX,
B.ColumnY,
...
FROM
dbo.TableReturningFunc2(@StaticParam1, @StaticParam2) AS B
WHERE
B.Key = P.Key
FOR XML AUTO, TYPE
)
FROM
(
<joined tables here>
) AS P
FOR XML AUTO,ROOT('ROOT')
Run Code Online (Sandbox Code Playgroud)
P具有~5000行A和B~4000行
此查询的运行时性能约为10 +分钟.
但是将它更改为:
SELECT
P.Column1,
P.Column2,
P.Column3,
...
INTO #P
SELECT
A.ColumnX,
A.ColumnY,
...
INTO #A
FROM
dbo.TableReturningFunc1(@StaticParam1, @StaticParam2) AS A
SELECT
B.ColumnX,
B.ColumnY, …
Run Code Online (Sandbox Code Playgroud) 场景:在git中有每个(活动)版本的分支,
顺序是:
Jane必须从共享中获取R2并在她可以推送之前处理合并.但是,她不知道如何处理鲍勃的变化.
分支:R1,R2
State of Shared Repository
C1 - Bob
|
C2-+ - Jane
| |
| C3 - George
| |
| C4
C5 | - Bob
| |
C6 | - Jane [R1]
|
C7 - …
Run Code Online (Sandbox Code Playgroud) 我认为目前的语言不存在这种支持.我认为我想做的事情可以通过"工作流引擎"来解决.但我对工作流程的问题通常是:
我已经研究了在C#中序列化迭代器,但这并没有让我到达我想要的位置.我目前正在考虑在Boo中组装一个DSL,但不确定我是否能够在Boo中获得类似coroutine的行为,并且能够将其序列化.
这是我想做的有限虚构的例子.主要问题是,在例程中的任何时候,您可能需要获得用户输入.输入之间的时间可能很长,因此需要将服务状态序列化为磁盘.
def RunMachine(user)
var lever = user.ChooseLever()
lever.Pull()
var device = CreateDevice(user)
machine.Add(device)
machine.Run()
def CreateDevice(user)
var color = user.ChooseColor()
var shape = user.ChooseShape()
return Device(color, shape)
Run Code Online (Sandbox Code Playgroud)
我在CPython中有一个工作"引擎".它捎带在python中的迭代器/ yield支持上.所以代码看起来像这样:
def escape(self, you):
roll = yield self.game.rollDice(you)
if roll < 5:
self.caughtAction(you)
Run Code Online (Sandbox Code Playgroud)
哪里rollDice
可以打断.用一些用户动作.但是,CPython不会序列化迭代器.
由于游戏的整个状态可以定义为一系列命令,因此我将游戏状态序列化为协程开始的点,然后是剩余的命令列表.所以保存/恢复如下所示:
def dumpGameState(game):
if gameState.partialState:
return pickle.dumps({ 'partialState': game.partialState, 'partialInputs': game.partialInputs })
return pickle.dumps(game)
def loadGameState(data):
state = pickle.loads(data)
if state.__class__ is …
Run Code Online (Sandbox Code Playgroud) 我似乎无法获得Flex 3想要解压缩的流.
我试过了:
这些似乎都没有让人ByteArray.uncompress
高兴,即我得到了
错误#2058:解压缩数据时出错.
整个Deflate vs zlib让我绕圈子走了.
似乎根据维基百科的文章,zlib是DEFLATE的一个实现.但根据Actionscript他们是两个不同的东西?
微软也似乎预示着Gzip已至少使用deflate算法,在他们的文档,他们指的是GZipOutputStream使用相同的压缩算法DeflateStream.所以我假设它只是一个头的区别,这表明这是"没有好"至于"ByteArray.uncompress"为使用"deflate"算法在AIR应用程序仅支持.
示例"服务器"代码,在这种情况下使用SharpZipLib(不工作):
public virtual bool ProcessRequest(string path, HttpListenerContext context)
{
var buffer = File.ReadAllBytes(path);
// Specifying to strip header/footer from data as that seems to be what the
// docs for ByteArray.uncompress indicate is necessary
var deflater = new Deflater(Deflater.DEFAULT_COMPRESSION, true);
using (var zipStream = new DeflaterOutputStream(context.Response.OutputStream, deflater))
{
zipStream.Write(buffer, 0, buffer.Length);
}
}
Run Code Online (Sandbox Code Playgroud) 我知道使用匿名函数,本地堆栈变量被提升为一个类,现在在堆上等等.所以以下方法不起作用:
using System;
using System.Collections.Generic;
using System.Linq;
namespace AnonymousFuncTest
{
class Program
{
static void Main(string[] args)
{
foreach (var f in GetFuncs())
{
Console.WriteLine(f());
}
Console.ReadLine();
}
static IEnumerable<Func<int>> GetFuncs()
{
List<Func<int>> list = new List<Func<int>>();
foreach(var i in Enumerable.Range(1, 20))
{
list.Add(delegate() { return i; });
}
return list;
}
}
}
Run Code Online (Sandbox Code Playgroud)
我知道将GetFuncs更改为可行的方法:
static IEnumerable<Func<int>> GetFuncs()
{
foreach(var i in Enumerable.Range(1, 20))
{
yield return () => i;
}
}
Run Code Online (Sandbox Code Playgroud)
但是说我做的事情如下:
foreach (var arg in someArgList)
{
var …
Run Code Online (Sandbox Code Playgroud)