2010-07-17 17 views
13

que tiene un simple tipo de valor:números de serie a consecuencia de un LINQ IEnumerable

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

que, como se le nota es serializable. Entonces tengo una lista de estos:

static private List<TimerInstance> _Timers = new List<TimerInstance>(); 

y un método de LINQ para eliminar la parte inferior 5% y el 5% de los contadores de tiempo de la lista:

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

Entonces estoy tratando de Seralize a XML el resultado de esta enumeración, es decir serializar sólo los valores de los temporizadores en el medio 90%, la eliminación de la parte superior e inferior 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()); 
} 

el problema es que cuando este código se ejecuta, consigo este:

Una primera excepción del tipo 'System.Runtime.Serialization.SerializationException' producido en mscorlib.dll Microsoft.WindowsAzure.ServiceRuntime crítico: 1: Excepción no controlada: System.Runtime.Serialization.SerializationException: Escriba 'System.Linq.Enumerable + d__3a`1 [[TracePerfWorker.TraceTimer + TimerInstance, TracePerfWorker, Version = 1.0.0.0, Culture = neutral, PublicKeyToken = null]]' en Assembly 'System.Core, Version = 4.0. 0.0, Culture = neutral, PublicKeyToken = b77a5c561934e089 'no está marcado como serializable. en System.Runtime.Serialization.FormatterServices.InternalGetSerializableMembers (RuntimeType tipo) en System.Runtime.Serialization.FormatterServices.GetSerializableMembers (Tipo tipo, el contexto StreamingContext) en System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitMemberInfo() en System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitSerialize (Object obj , ISurrogateSelector surrogateSelector, el contexto StreamingContext, serObjectInfoInit serObjectInfoInit, convertidor IFormatterConverter, objectWriter objectWriter, aglutinante SerializationBinder) en System.Runtime.Serialization. Formatters.Binary.WriteObjectInfo.Serialize (Object obj, ISurrogateSelector surrogateSelector, el contexto StreamingContext, SerObjectInfoInit serObjectInfoInit, convertidor IFormatterConverter, ObjectWriter objectWriter, aglutinante SerializationBinder) en System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Serialize (Object gráfica, Header [] inHeaders, __BinaryWriter serWriter , Boolean fcheck) en System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize (corriente serializationStream, gráfico de objetos, Header [] cabeceras, Boolean fcheck) en System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize (Stream serializationStream, gráfico de objetos) en TracePerfWorker.TraceTimer.SerializeTimersToStream (Stream s) en c: \ Users \ M Ike \ documentos \ Visual Studio 2010 \ Projects \ AzureTracePerfTest \ TracePerfWorker \ TraceTimer.cs: Línea 88 en TracePerfWorker.WorkerRole.SerializeTimersToBlob (String strTimerGroupName) en c: \ Users \ Mike \ Documentos \ Visual Studio 2010 \ Projects \ AzureTracePerfTest \ TracePerfWorker \ WorkerRole.cs: línea en TracePerfWorker.WorkerRole.DoWorkNoTrace() en c: \ Users \ Mike \ Documents \ Visual Studio 2010 \ Projects \ AzureTracePerfTest \ TracePerfWorker \ WorkerRole.CS: Línea 153 en TracePerfWorker.WorkerRole.Run() en c: \ Users \ Mike \ documentos \ Visual Studio 2010 \ Projects \ AzureTracePerfTest \ TracePerfWorker \ WorkerRole.cs: Línea 77 en Microsoft.WindowsAzure.ServiceRuntime.RoleEnvironment .StartRoleInternal() en Microsoft.WindowsAzure.ServiceRuntime.RoleEnvironment.StartRole() en Microsoft.WindowsAzure.ServiceRuntime.Implementation.Loader.RoleRuntimeBridge.b__1() en System.Threading.ThreadHelper.ThreadStart_Context (estado Object) en Sistema .Threading.ExecutionContext.Run (ExecutionContext executionContext, devolución de llamada ContextCallback, estado Objeto, Boolean ignoreSyncCtx) en System.Threading.ExecutionContext.Run (ExecutionContext executio nContext, ContextCallback de devolución de llamada, el estado del objeto) en System.Threading.ThreadHelper.ThreadStart()

creo que tengo lo que esto me está diciendo - la clase implícita de que el empadronador aparentemente ha generado ('System.Linq. Enumerable + d__3a`1 [[TracePerfWorker.TraceTimer + TimerInstance, TracePerfWorker ') no está marcado como serializable.

Pero esto parece una situación muy común, donde tomo un valor serializable tipo (TimerInstance), y simplemente construyo una consulta LINQ sobre una lista de estos valores, es decir, el enumerador simplemente está devolviendo valores de TimerInstance - cómo ¿Entonces lo convenzo de que lo que el enumerador está devolviendo es solo una lista de valores de TimerInstance, que son serializables?

Respuesta

15

¿Qué le parece usar ToList para obtener una lista de artículos antes de llamar serialize? necesitará su método que ser cambiado para devolver un List<TimerInstance> en lugar de IEnumerable<TimerInstance>

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

+4

En realidad, el tipo de retorno método puede permanecer como 'IEnumerable '. Solo agregar el 'ToList' es suficiente. –

+0

Gracias. Eso lo hizo. –

+0

ToList() resolvió mi problema también: var timestamps = (de t en Enumerable.Range (1, chunk_samples) .Reverse() select now - t/sampling_rate). ToList(); –

Cuestiones relacionadas