У меня есть простой тип значения:
[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 to 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());
}
Проблема в том, что когда этот код выполняется, я получаю следующее:
Первое случайное исключение типа "System.Runtime.Serialization.SerializationException" произошло в mscorlib.dll Microsoft.WindowsAzure.ServiceRuntime Критический: 1: Необработанное исключение: System.Runtime.Serialization.SerializationException: Type 'System.Linq.Enumerable + d__3a`1 [[TracePerfWorker.TraceTimer + TimerInstance, TracePerfWorker, Version = 1.0.0.0, Культура = нейтральная, PublicKeyToken = null]] 'в Assembly' System.Core, Version = 4.0.0.0, Культура = нейтральная, PublicKeyToken = b77a5c561934e089 'не отмечена как сериализации. в System.Runtime.Serialization.FormatterServices.InternalGetSerializableMembers(RuntimeType тип) в System.Runtime.Serialization.FormatterServices.GetSerializableMembers(Тип тип, контекст StreamingContext) в System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitMemberInfo() в System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitSerialize(объект obj, ISurrogateSelector surrogateSelector, Streaming Контекстный контекст, SerObjectInfoInit serObjectInfoInit, преобразователь IFormatterConverter, ObjectWriter objectWriter, SerializationBinder binder) в System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.Serialize(Object obj, ISurrogateSelector surrogateSelector, Streaming Контекстный контекст, SerObjectInfoInit serObjectInfoInit, преобразователь IFormatterConverter, ObjectWriter objectWriter, SerializationBinder binder) в System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Serialize(объект graph, Header [] inHeaders, __BinaryWriter serWriter, Boolean fCheck) в System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(поток serializationStream, граф объектов, заголовки [], Boolean fCheck) в System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(поток serializationStream, граф объектов) в TracePerfWorker.TraceTimer.SerializeTimersToStream(поток s) в c:\Users\Mike\Documents\Visual Studio 2010\Projects\AzureTracePerfTest\TracePerfWorker\TraceTimer.cs: строка 88 в TracePerfWorker.WorkerRole.SerializeTimersToBlob(String strTimerGroupName) в c:\Users\Mike\Documents\Visual Studio 2010\Projects\AzureTracePerfTest\TracePerfWorker\WorkerRole.cs: линия 192 в TracePerfWorker.WorkerRole.DoWorkNoTrace() в c:\Users\Mike\Documents\Visual Studio 2010\Projects\AzureTracePerfTest\TracePerfWorker\WorkerRole.cs: линия 153 в TracePerfWorker.WorkerRole.Run() в c:\Users\Mike\Documents\Visual Studio 2010\Projects\AzureTracePerfTest\TracePerfWorker\WorkerRole.cs: строка 77 в Microsoft.WindowsAzure.ServiceRuntime.RoleEnvironment.StartRoleInternal() в Microsoft.WindowsAzure.ServiceRuntime.RoleEnvironment.StartRole() в Microsoft.WindowsAzure.ServiceRuntime.Implementation.Loader.RoleRuntimeBridge.b__1() в System.Threading.ThreadHelper.ThreadStart_Context (состояние объекта) в System.Threading.ExecutionContext.Run(ExecutionContext executeContext, обратный вызов ContextCallback, состояние объекта, логическое значение ignoreSyncCtx) в System.Threading.ExecutionContext.Run(ExecutionContext executeContext, обратный вызов ContextCallback, состояние объекта) в System.Threading.ThreadHelper.ThreadStart()
Я думаю, что получаю то, что это говорит мне - неявный класс, который, по-видимому, сгенерировал (например, "System.Linq.Enumerable + d__3a`1 [[TracePerfWorker.TraceTimer + TimerInstance, TracePerfWorker" ) сам по себе не является сериализуемым.
Но это похоже на действительно распространенную ситуацию, когда я беру сериализуемый тип значения (TimerInstance) и просто построение LINQ-запроса по списку этих значений, т.е. Перечислитель просто возвращает значения TimerInstance - как я могу затем убедить его, что возвращаемый счетчик представляет собой список значений TimerInstance, которые могут быть сериализованы?