У меня есть простой тип значения:
[Serializable]
private struct TimerInstance
{
public TimerInstance(string str, long nTicks)
{
_name = str;
_ticks = nTicks;
}
private readonly string _name;
private readonly long _ticks;
public string Name { get { return _name; } }
public long Ticks { get { return _ticks; } }
public override string ToString()
{
return string.Format("{0,20}: {1,10:N}", Name, Ticks);
}
}
который, как Вы отметите, является сериализуемым. Затем у меня есть список их:
static private List<TimerInstance> _Timers = new List<TimerInstance>();
и метод LINQ для устранения нижней части 5% и лучших 5% таймеров из списка:
// Return items that should be persisted. By convention, we are eliminating the "outlier"
// values which I've defined as the top and bottom 5% of timer values.
private static IEnumerable<TimerInstance> ItemsToPersist()
{
// Eliminate top and bottom 5% of timers from the enumeration. Figure out how many items
// to skip on both ends.
int iFivePercentOfTimers = _Timers.Count / 20;
int iNinetyPercentOfTimers = _Timers.Count - iFivePercentOfTimers * 2;
return (from x in _Timers
orderby x.Ticks descending
select x).Skip(iFivePercentOfTimers).Take(iNinetyPercentOfTimers);
}
Я затем пробую к Seralize к XML результат этого перечисления, т.е. сериализирую просто значения таймеров в средних 90%, устраняя вершину и нижнюю часть 5%:
// Serialize the timer list as XML to a stream - for storing in an Azure Blob
public static void SerializeTimersToStream(Stream s)
{
BinaryFormatter f = new BinaryFormatter();
f.Serialize(s, ItemsToPersist());
}
Проблема состоит в том, что, когда этот код выполняется, я получаю это:
Первое случайное исключение типа 'Система. Время выполнения. Сериализация. SerializationException' произошел в mscorlib.dll Microsoft. WindowsAzure. Очень важный ServiceRuntime: 1: Необработанное исключение: Система. Время выполнения. Сериализация. SerializationException: Введите 'Систему. Linq. Enumerable+d __ 3a '1 [[TracePerfWorker. TraceTimer+TimerInstance, TracePerfWorker, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]' в блоке 'Система. Ядро, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' не отмечены как сериализуемые. в System. Время выполнения. Сериализация. FormatterServices. InternalGetSerializableMembers (тип RuntimeType) в System. Время выполнения. Сериализация. FormatterServices. GetSerializableMembers (Вводят тип, контекст StreamingContext) в System. Время выполнения. Сериализация. Средства форматирования. Двоичный файл. WriteObjectInfo. InitMemberInfo () в Системе. Время выполнения. Сериализация. Средства форматирования. Двоичный файл. WriteObjectInfo. InitSerialize (Возражают obj, ISurrogateSelector surrogateSelector, контексту StreamingContext, SerObjectInfoInit serObjectInfoInit, преобразователю IFormatterConverter, ObjectWriter objectWriter, редактору связей SerializationBinder) в System. Время выполнения. Сериализация. Средства форматирования. Двоичный файл. WriteObjectInfo. Сериализируйте (Возразите obj, ISurrogateSelector surrogateSelector, контексту StreamingContext, SerObjectInfoInit serObjectInfoInit, преобразователю IFormatterConverter, ObjectWriter objectWriter, редактору связей SerializationBinder) в System. Время выполнения. Сериализация. Средства форматирования. Двоичный файл. ObjectWriter. Сериализируйте (Граф объектов, Заголовок [] inHeaders, __ BinaryWriter serWriter, булевская переменная fCheck) в System. Время выполнения. Сериализация. Средства форматирования. Двоичный файл. BinaryFormatter. Сериализируйте (Поток serializationStream, Граф объектов, Заголовок [] заголовки, булевская переменная fCheck) в System. Время выполнения. Сериализация. Средства форматирования. Двоичный файл. BinaryFormatter. Сериализируйте (Поток serializationStream, Граф объектов) в TracePerfWorker. TraceTimer. SerializeTimersToStream (Поток s) в c:\Users\Mike\Documents\Visual Studio 2010\Projects\AzureTracePerfTest\TracePerfWorker\TraceTimer.cs:line 88 в TracePerfWorker. WorkerRole. SerializeTimersToBlob (Представляют strTimerGroupName в виде строки) в c:\Users\Mike\Documents\Visual Studio 2010\Projects\AzureTracePerfTest\TracePerfWorker\WorkerRole.cs:line 192 в TracePerfWorker. WorkerRole. DoWorkNoTrace () в c:\Users\Mike\Documents\Visual Studio 2010\Projects\AzureTracePerfTest\TracePerfWorker\WorkerRole.cs:line 153 в TracePerfWorker. WorkerRole. Выполненный () в c:\Users\Mike\Documents\Visual Studio 2010\Projects\AzureTracePerfTest\TracePerfWorker\WorkerRole.cs:line 77 в Microsoft. WindowsAzure. ServiceRuntime. RoleEnvironment. StartRoleInternal () в Microsoft. WindowsAzure. ServiceRuntime. RoleEnvironment. StartRole () в Microsoft. WindowsAzure. ServiceRuntime. Реализация. Загрузчик. RoleRuntimeBridge.b __ 1 () в Системе. Поточная обработка. ThreadHelper. ThreadStart_Context (Объектное состояние) в System. Поточная обработка. ExecutionContext. Выполненный (ExecutionContext executionContext, обратный вызов ContextCallback, Объектное состояние, булевская переменная ignoreSyncCtx) в System. Поточная обработка. ExecutionContext. Выполненный (ExecutionContext executionContext, обратный вызов ContextCallback, Объектное состояние) в System. Поточная обработка. ThreadHelper. ThreadStart ()
Я думаю, что получаю то, что это говорит мне - неявный класс, что перечислитель, по-видимому, генерировал ('Система. Linq. Enumerable+d __ 3a '1 [[TracePerfWorker. TraceTimer+TimerInstance, TracePerfWorker'), самостоятельно не отмечен как сериализуемый.
Но это походит на действительно общую ситуацию, где я беру сериализуемый тип значения (TimerInstance) и просто создаю запрос LINQ по списку этих значений, т.е. перечислитель просто возвращает значения TimerInstance - как я затем убеждаю его, который, что возвращает перечислитель, просто список значений TimerInstance, которые являются сериализуемыми?
Как насчет использования ToList для получения списка элементов перед вызовом serialize?
Ваш метод необходимо будет изменить, чтобы он возвращал List
вместо IEnumerable