Сериализация результата LINQ IEnumerable - PullRequest
14 голосов
/ 17 июля 2010

У меня есть простой тип значения:

    [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);
}

Затем я пытаюсьСерализовать в 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: Тип 'System.Linq.Enumerable + d__3a`1 [[TracePerfWorker.TraceTimer + TimerInstance, TracePerfWorker, Версия = 1.0.0.0, Культура = нейтральный, PublicKeyToken = null]]' в сборке 'System.Core, Версия = 4.0.0.0, Культура = нейтральный, PublicKeyToken = b77a5c561934e089 'не помечен как сериализуемый.в System.Runtime.Serialization.FormatterServices.InternalGetSerializableMembers (тип RuntimeType) в System.Runtime.Serialization.FormatterServices.GetSerializableMembers (Тип тип, контекст StreamingContext) в System.Runtime.Serialization.Formatters.Binary.WefoMject (atfoOject)Runtime.Serialization., ISurrogateSelector surrogateSelector, контекст StreamingContext, SerObjectInfoInit serObjectInfoInit, преобразователь IFormatterConverter, ObjectWriter objectWriter, связыватель SerializationBinder) в System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Serialize, SyntherWerHer_WeWer_WeWR)stem.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize (поток serializationStream, граф объектов, заголовки [], логический fCheck) в System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize (поток serializationStream, граф объектов) вTracePerfWorker.\ Mike \ Documents \ Visual Studio 2010 \ Projects \ AzureTracePerfTest \ TracePerfWorker \ WorkerRole.cs: строка 192 в 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_Conxt.Выполнить (ExecutionContext executeContext, обратный вызов ContextCallback, состояние объекта, Boolean ignoreSyncCtx) в System.Threading.ExecutionContext.Run (Обратный вызов ExecutionContext executeContext, ContextCallback, состояние объекта) в System.Threading.ThreadHelper.ThreadStart ()

1017

Мне кажется, я понимаю, что это говорит мне - неявный класс, который, по-видимому, сгенерирован перечислителем ('System.Linq.Enumerable + d__3a`1 [[TracePerfWorker.TraceTimer + TimerInstance, TracePerfWorker') сам по себе не помечен как сериализуемый.

Но это кажется довольно распространенной ситуацией, когда я беру сериализуемый тип значения (TimerInstance) и просто строю запрос LINQ по списку этих значений, то есть перечислитель просто возвращает значения TimerInstance.- как мне тогда убедить его в том, что перечислитель возвращает просто список значений TimerInstance, которые можно сериализовать?

1 Ответ

16 голосов
/ 17 июля 2010

Как насчет использования ToList для получения списка элементов перед вызовом serialize?Ваш метод нужно будет изменить, чтобы он возвращал List<TimerInstance> вместо IEnumerable<TimerInstance>

http://msdn.microsoft.com/en-us/library/bb342261.aspx

...