2010-07-17 31 views
13

Tôi có một kiểu giá trị đơn giản:Serializing kết quả của một 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); 
     } 
    } 

mà như bạn sẽ lưu ý là serializable. Sau đó, tôi có một danh sách sau đây:

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

và một phương pháp LINQ để loại bỏ dưới 5% và top 5% của giờ từ danh sách:

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

sau đó Tôi cố gắng để Seralize to XML kết quả của điều tra này, tức là serialize chỉ các giá trị của tính giờ ở giữa 90%, loại bỏ các đỉnh và đáy 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()); 
} 

vấn đề là khi mã này thực hiện, tôi có được điều này:

Một ngoại lệ cơ hội đầu tiên của loại 'System.Runtime.Serialization.SerializationException' xảy ra ở mscorlib.dll Microsoft.WindowsAzure.ServiceRuntime Critical: 1: Unhandled Exception: System.Runtime.Serialization.SerializationException: Nhập 'System.Linq.Enumerable + d__3a`1 [[TracePerfWorker.TraceTimer + TimerInstance, TracePerfWorker, Phiên bản = 1.0.0.0, Văn hóa = trung lập, PublicKeyToken = null]]' trong Assembly 'System.Core, Version = 4.0. 0.0, Văn hóa = trung lập, PublicKeyToken = b77a5c561934e089 'không được đánh dấu là có thể tuần tự hóa. tại System.Runtime.Serialization.FormatterServices.InternalGetSerializableMembers (RuntimeType loại) tại System.Runtime.Serialization.FormatterServices.GetSerializableMembers (Type loại, StreamingContext ngữ cảnh) tại System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitMemberInfo() tại System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitSerialize (Object obj , ISurrogateSelector surrogateSelector, StreamingContext bối cảnh, SerObjectInfoInit serObjectInfoInit, IFormatterConverter chuyển đổi, ObjectWriter objectWriter, SerializationBinder binder) tại System.Runtime.Serialization. Formatters.Binary.WriteObjectInfo.Serialize (Object obj, ISurrogateSelector surrogateSelector, StreamingContext bối cảnh, SerObjectInfoInit serObjectInfoInit, IFormatterConverter chuyển đổi, ObjectWriter objectWriter, SerializationBinder binder) tại System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Serialize (Object đồ thị, header [] inHeaders, __BinaryWriter serWriter , Boolean fCheck) tại System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize (Dòng serializationStream, Object graph, Header [] headers, Boolean fCheck) tại System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize (Phát trực tiếp serializationStream, Object graph) tại TracePerfWorker.TraceTimer.SerializeTimersToStream (Stream s) trong c: \ Users \ M ike \ Documents \ Visual Studio 2010 \ Projects \ AzureTracePerfTest \ TracePerfWorker \ TraceTimer.cs: dòng 88 tại TracePerfWorker.WorkerRole.SerializeTimersToBlob (Chuỗi strTimerGroupName) trong c: \ Users \ Mike \ Documents \ Visual Studio 2010 \ Projects \ AzureTracePerfTest \ TracePerfWorker \ WorkerRole.cs: dòng tại TracePerfWorker.WorkerRole.DoWorkNoTrace() trong c: \ Users \ Mike \ Documents \ Visual Studio 2010 \ Projects \ AzureTracePerfTest \ TracePerfWorker \ WorkerRole.cs: dòng tại TracePerfWorker.WorkerRole.Run() trong c: \ Users \ Mike \ Documents \ Visual Studio 2010 \ Projects \ AzureTracePerfTest \ TracePerfWorker \ WorkerRole.cs: dòng 77 tại Microsoft.WindowsAzure.ServiceRuntime.RoleEnvironment .StartRoleInternal() tại Microsoft.WindowsAzure.ServiceRuntime.RoleEnvironment.StartRole() tại Microsoft.WindowsAzure.ServiceRuntime.Implementation.Loader.RoleRuntimeBridge.b__1() tại System.Threading.ThreadHelper.ThreadStart_Context (bang Object) tại hệ thống .Threading.ExecutionContext.Run (ExecutionContext executeContext, ContextCallback gọi lại, Trạng thái đối tượng, Boolean ignoreSyncCtx) tại System.Threading.ExecutionContext.Run (ExecutionContext executio nContext, ContextCallback callback, tiểu bang Object) tại System.Threading.ThreadHelper.ThreadStart()

Tôi nghĩ rằng tôi có được điều này là nói cho tôi - lớp ngầm rằng các điều tra viên đã rõ ràng được tạo ra ('System.Linq. Enumerable + d__3a`1 [[TracePerfWorker.TraceTimer + TimerInstance, TracePerfWorker ') không được đánh dấu là serializable. Nhưng điều này có vẻ như một tình huống thực sự phổ biến, nơi tôi đang dùng một kiểu giá trị có thể tuần tự (TimerInstance), và chỉ cần xây dựng truy vấn LINQ trên danh sách các giá trị này, tức là điều tra viên chỉ trả về giá trị TimerInstance - cách thức thế nào để tôi sau đó thuyết phục nó rằng những gì các điều tra viên đang trở lại chỉ là một danh sách các giá trị TimerInstance, được serializable?

Trả lời

15

Cách sử dụng ToList để nhận danh sách các mục trước khi bạn gọi serialize? phương pháp của bạn sẽ cần phải được thay đổi để trở về một List<TimerInstance> thay vì IEnumerable<TimerInstance>

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

+4

Trên thực tế, loại phương thức hoàn trả có thể ở lại là 'IEnumerable '. Chỉ cần thêm 'ToList' là đủ. –

+0

Cảm ơn. Điều đó đã làm điều đó. –

+0

ToList() cũng đã giải quyết vấn đề của tôi: var timestamps = (từ t trong Enumerable.Range (1, chunk_samples) .Reverse() chọn ngay bây giờ - t/sampling_rate) .ToList(); –

Các vấn đề liên quan