Сериализация анонимных делегатов в C #

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

Основная проблема, о которой я могу думать, может быть проблемой, заключается в том, что анонимный class является внутренней детализацией компилятора, и его структура не гарантируется постоянной между версиями .NET Framework. Я вполне уверен, что это так основано на моих исследованиях аналогичной проблемы с iteratorами.

Задний план

Я изучаю сериализацию анонимных функций. Я ожидал, что это не сработает, но обнаружил, что это произошло в некоторых случаях. Пока lambda не * и не вынуждает компилятор генерировать анонимный class, все работает нормально.

Исключение SerializationException выдается, если компилятор требует, чтобы сгенерированный class реализовал анонимную функцию. Это связано с тем, что class сгенерированный компилятором не помечен как сериализуемый.

пример

 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 succeeds = () => 5; f.Serialize(m, succeeds); // Example 2 Other o = new Other(); Func 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

Это похоже на вопрос о попытке сериализации iteratorов, и я нашел следующий код в предыдущем поиске (см. Countingdemo). Используя код из листинга 1 и ISurrogateSelector, я смог успешно сериализовать и десериализовать второй неудачный пример.

Задача

У меня есть система, которая открывается через веб-службу. Система имеет сложное, но маленькое состояние (много объектов, не много свойств для каждого объекта). Состояние сохраняется в кэше ASP.NET, но также сериализуется в BLOB в SQL в случае истечения срока действия кэша. Некоторые объекты должны выполнять произвольные «события» при достижении некоторого состояния. Следовательно, у них есть свойства, принимающие объекты Action / Func. Продуманный пример:

  class Command { public Command(Action action, Func condition); } 

Где-нибудь еще

  void DoSomethingWithThing(Thing thing) { state = Store.GetCurrentState(); Command cmd = new Command(() => thing.Foo(), () => thing.IsReady()) state.Add(cmd); Store.Save(state); } 

Вы видели это сообщение, которое я написал в качестве примера для CountingDemo: http://dotnet.agilekiwi.com/blog/2007/12/update-on-persistent-iterators.html ? К сожалению, Microsoft подтвердила, что они, вероятно, изменят детали компилятора (один день), что может вызвать проблемы. (например, f / при обновлении нового компилятора вы не сможете десериализовать материал, который вы сохранили в старом (текущем) компиляторе.)

Некоторым объектам необходимо выполнить произвольные «события», достигающие некоторого условия.

Насколько произвольны эти события? Можно ли их подсчитать, присвоить идентификаторы и сопоставить их по ссылке?

 public class Command where T : ISerializable { T _target; int _actionId; int _conditionId; public Command(T Target, int ActionId, int ConditionId) { _target = Target; _actionId = ActionId; _conditionId = ConditionId; } public bool FireRule() { Func theCondition = conditionMap.LookupCondition(_conditionId) Action theAction = actionMap.LookupAction(_actionId); if (theCondition(_target)) { theAction(_target); return true; } return false; } } 

Вся идея сериализации делегата очень рискованна. Теперь выражение может иметь смысл, но даже это трудно выразить, хотя образцы dynamic-LINQ каким-то образом способствуют форме текстового выражения.

Что именно вы хотите сделать с сериализованным делегатом? Я действительно не думаю, что это хорошая идея …

Поскольку это состояние является локальным, это приводит к проблемам при попытке настроить сопоставление.

Разве местное государство не представило бы такие же проблемы для сериализации?

Предположим, что компилятор и структура позволили этому работать:

 Other o = FromSomeWhere(); Thing t = OtherPlace(); target.OnWhatever = () => t.DoFoo() + o.DoBar(); target.Save(); 

Наверное, t и o также должны были быть сериализованы. Способы не имеют состояния, это случается.

Позже вы десериализуете цель. Разве вы не получаете новые копии t и o? Разве эти копии не будут синхронизированы с любыми изменениями в оригинале t и o?

Кроме того: нельзя ли назвать этот пример вручную?

 Other o = FromSomeWhere(); Thing t = OtherPlace(); target.OnWhatever = new DoFooBar() {Other = o, Thing = t} .Run; target.Save(); 

Я не на это 100%, но я считаю, что если вы хотите «сохранить» делегата или какой-то код в базе данных, которая может быть довольно динамичной, вам нужно создать Expression, тогда вы можете скомпилировать выражение в Func <...>.

Основы дерева выражений

Поздно связанные вызовы с деревьями выражений

Карта функций не позволит мне использовать локальное состояние в действии / условиях. Единственный способ обойти это – создать class для каждой функции, требующей дополнительного состояния.

Это то, что компилятор C # делает для меня автоматически с анонимными функциями. Моя проблема – сериализация этих classов компилятора.

  Other o = FromSomeWhere(); Thing t = OtherPlace(); target.OnWhatever = () => t.DoFoo() + o.DoBar(); target.Save();c 

Попытка сериализации, которая потерпит неудачу. Поскольку это состояние является локальным, это приводит к проблемам при попытке настроить сопоставление. Вместо этого я должен был бы объявить что-то вроде этого:

 [Serializable] abstract class Command { public abstract T Run(); } class DoFooBar : Command { public Other Other { get; set; } public Thing Thing { get; set; } public override int Run() { return Thing.DoFoo() + Other.DoBar(); } } 

и затем используйте его следующим образом:

  DoFooBar cmd = new DoFooBar(); cmd.Other = FromSomewhere(); cmd.Thing = OtherPlace(); target.OnWhatever = cmd.Run; target.Save(); 

По сути, это означает, что вручную выполняет то, что делает компилятор C # для меня автоматически.

  • Как я могу расширить лексический бросок, чтобы поддерживать перечисленные типы?
  • Исправлено столбец IOException, записывающий сериализуемый объект getactivity ()
  • Сериализация / десериализация с streamом памяти
  • Сериализация прерываний в .NET 4.5
  • Как называются конструкторы во время сериализации и десериализации?
  • Переносимость двоичной сериализации типа double / float в C ++
  • Как узнать, когда вы загрузились через XML-сериализацию?
  • Что библиотека JSON хорошо работает для вас в .NET?
  • Могу ли я заставить XmlSerializer игнорировать пространство имен при десериализации?
  • Каков правильный способ создания пользовательского .NET Exception сериализуемым?
  • Неверный регистр
  • Interesting Posts

    Как избежать привязки внутри метода рендеринга

    Mysql, как исправить Доступ запрещен для пользователя 'root' @ 'localhost'

    printf (“% d% d% d \ n”, ++ a, a ++, a) output

    Как перехватить вызов метода со стандартными функциями Java (без AspectJ и т. Д.)?

    Проверка даты с помощью проверки подлинности ASP.NET

    Как я основываю правило перспективы на число адресов «Кому:»?

    Du и ls сообщают о разном размере каталога?

    Запуск Linux на старом ПК

    Переместить некоторые элементы библиотеки iTunes на другой диск?

    Vim: Как синхронизировать NERDTree с текущим открытым файлом пути к вкладке?

    Что значит «выровнять» разделы?

    Событие jQuery click не работает после добавления classа

    Как восстановить раздел «Избранное» в проводнике после того, как все записи были удалены?

    Использование wget для рекурсивного извлечения каталога с произвольными файлами в нем

    Rails упорядочивает по результатам подсчет has_many association

    Давайте будем гением компьютера.