Я пытаюсь определить, какие проблемы могут быть вызваны использованием следующего суррогата сериализации, чтобы разрешить сериализацию анонимных функций /delegate/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;
}
}
Листинг 1, адаптированный из Подсчет демо
Основная проблема, о которой я могу думать, может быть проблемой, заключается в том, что анонимный класс является внутренней детализацией компилятора, и структура не гарантируется постоянной между версиями .NET Framework. Я довольно уверен, что это так основано на моих исследованиях аналогичной проблемы с итераторами.
Фон
Я изучаю сериализацию анонимных функций. Я ожидал, что это не сработает, но обнаружил, что это произошло в некоторых случаях. Пока лямбда не * и & заставить компилятор генерировать анонимный класс, все работает отлично.
Вызывается SerializationException, если компилятор требует, чтобы сгенерированный класс реализовал анонимную функцию. Это связано с тем, что класс, сгенерированный компилятором, не помечен как сериализуемый.
Пример
namespace Example
{
[Serializable]
class Other
{
public int Value;
}
[Serializable]
class Program
{
static void Main(string[] args)
{
MemoryStream m = new MemoryStream();
BinaryFormatter f = new BinaryFormatter();
// Example 1
Func<int> succeeds = () => 5;
f.Serialize(m, succeeds);
// Example 2
Other o = new Other();
Func<int> fails = () => o.Value;
f.Serialize(m, fails); // throws SerializationException - Type 'Example.Program+<>c__DisplayClass3' in Assembly 'Example, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' is not marked as serializable.
}
}
Листинг 2
Это похоже на вопрос о попытке сериализации итераторов, и я нашел следующий код в предыдущем поиске (см. countingdemo) Используя код из Листинг 1 и ISurrogateSelector, я смог успешно сериализовать и десериализовать второй неудачный пример.
Цель
У меня есть система, которая открывается через веб-службу. Система имеет сложное, но маленькое состояние (много объектов, не много свойств для каждого объекта). Состояние сохраняется в кэше ASP.NET, но также сериализуется в BLOB в SQL в случае истечения срока действия кэша. Некоторые объекты должны выполнять произвольные "события" при достижении некоторого состояния. Следовательно, у них есть свойства, принимающие объекты Action/Func. Продуманный пример:
class Command
{
public Command(Action action, Func<bool> condition);
}
Где-то в другом месте
void DoSomethingWithThing(Thing thing)
{
state = Store.GetCurrentState();
Command cmd = new Command(() => thing.Foo(), () => thing.IsReady())
state.Add(cmd);
Store.Save(state);
}