Я пытаюсь определить, какие проблемы могут быть вызваны с помощью следующего суррогата сериализации, чтобы включить сериализацию анонимных функций / делегата / лямбды.
// 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, но также сериализуется в большой двоичный объект в 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);
}