2011-07-20 65 views
5

Tôi muốn sử dụng một hàm WriteList (Danh sách giá trị) chung để viết một List bằng cách sử dụng BinaryWriter. Đây là mã tôi đang sử dụng:Làm cách nào để viết danh sách bằng BinaryWriter?

public void WriteList<T>(List<T> value) 
{ 
    for (int i = 0; i < value.Count; i++) 
    { 
     _writer.Write(value[i]); 
    } 
} 

Các lỗi tôi nhận được là:

Error 1 The best overloaded method match for 'System.IO.BinaryWriter.Write(bool)' has some invalid arguments  
Error 2 Argument 1: cannot convert from 'T' to 'bool' 

Các BinaryFormatter là hoàn toàn không một lựa chọn.

+3

bất kỳ ràng buộc nào đối với T? như T: struct? –

Trả lời

4

Nếu bạn kiểm tra các tài liệu cho BinaryWriter bạn sẽ thấy nó không chấp nhận một lập luận của đối tượng (Viết loại nguyên thủy), và trình biên dịch đang cố gắng hết sức mình tại một tình trạng quá tải, nhưng thất bại, vì bạn không thể cast T của bạn để bool, hoặc bất cứ điều gì khác mà BinarwWriter muốn.

Bạn sẽ phải chuyển đổi đối tượng của mình thành thứ gì đó mà BinaryWriter sẽ hoạt động.

+0

Chẳng hạn như ... bằng cách sử dụng sự phản chiếu để có được tất cả các thành viên kiểu giá trị của lớp, và sau đó viết chúng cái khác với BinaryWriter. Tôi cho rằng đây là một phần của câu trả lời của bạn, vì đó là nơi duy nhất bạn có thể đi với nó. – hoodaticus

+0

yea, nhưng ai muốn. bạn cũng có thể gặp sự cố nếu bạn có loại giá trị (struct) với loại tham chiếu làm thành viên. Nếu bạn thực sự muốn làm một cái gì đó, bạn có thể thực hiện một serializer tùy chỉnh để xuất như byte [] hoặc chuỗi vv sẽ muốn có một lý do thực sự tốt để làm điều này imo. – jasper

+0

Nghiêm túc! Lý do duy nhất mà tôi từng tìm thấy là vì bạn muốn có BinaryFormatter trong Silverlight. – hoodaticus

5

Tôi thực sự không nghĩ rằng bạn có thể tránh BinaryFormatter. Vì kiểu T có thể là bất kỳ kiểu phức tạp nào và mỗi thể hiện của T có thể biểu diễn một biểu đồ lớn các biến trên bộ nhớ.

vì vậy giải pháp duy nhất bạn có là để chuyển đổi bạn thể hiện của T để byte [] định dạng và các giải pháp đơn giản nhất cho điều đó là: BinaryFormatter

Thực ra lý do .Write() phương pháp duy nhất chấp nhận các loại nguyên thủy là nó biết cách chuyển đổi chúng trực tiếp thành byte [] (sử dụng Convert.ToXXX()) nhưng không có cách nào nó có thể đoán được cho kiểu generic T.

Như một công việc xung quanh bạn có thể định nghĩa một giao diện như sau:

public interface IBinarySerializable 
{ 
    byte[] GetBytes(); 
} 

và sau đó thực hiện t nó trong lớp học của bạn:

public class MyClass: IBinarySerializable 
{ 
    public int X {get;set;} 
    public byte[] GetBytes() 
    { 
     return BitConverter.GetBytes(X); // and anyother 
    } 
} 

và thay đổi phương thức của bạn như thế này:

public void WriteList<T>(List<T> value) where T:IBinarySerializable 
{ 
    for (int i = 0; i < value.Count; i++) 
    { 
     _writer.Write(value[i].GetBytes()); 
    } 
} 
4

Bạn không thể vượt qua một T tổng quát để BinaryWriter.Write - nó có quá tải cho nhiều loại cụ thể (bool, byte, byte [], int, string, v.v.), nhưng không có chung. Vì vậy, bạn sẽ cần phải làm điều đó cho mình, trong một số cách tương tự như mã dưới đây.

public void WriteList<T>(List<T> value) 
    { 
     for (int i = 0; i < value.Count; i++) 
     { 
      switch (Type.GetTypeCode(typeof(T))){ 
      //_writer.Write(value[i]); 
       case TypeCode.Boolean: 
        _writer.Write((bool)(object)value[i]); 
        break; 
       case TypeCode.Byte: 
        _writer.Write((byte)(object)value[i]); 
        break; 
       case TypeCode.Char: 
        _writer.Write((char)(object)value[i]); 
        break; 
       case TypeCode.Decimal: 
        _writer.Write((decimal)(object)value[i]); 
        break; 
       case TypeCode.Double: 
        _writer.Write((double)(object)value[i]); 
        break; 
       case TypeCode.Single: 
        _writer.Write((float)(object)value[i]); 
        break; 
       case TypeCode.Int16: 
        _writer.Write((short)(object)value[i]); 
        break; 
       case TypeCode.Int32: 
        _writer.Write((int)(object)value[i]); 
        break; 
       case TypeCode.Int64: 
        _writer.Write((short)(object)value[i]); 
        break; 
       case TypeCode.String: 
        _writer.Write((string)(object)value[i]); 
        break; 
       case TypeCode.SByte: 
        _writer.Write((sbyte)(object)value[i]); 
        break; 
       case TypeCode.UInt16: 
        _writer.Write((ushort)(object)value[i]); 
        break; 
       case TypeCode.UInt32: 
        _writer.Write((uint)(object)value[i]); 
        break; 
       case TypeCode.UInt64: 
        _writer.Write((ulong)(object)value[i]); 
        break; 
       default: 
        if (typeof(T) == typeof(byte[])) 
        { 
         _writer.Write((byte[])(object)value[i]); 
        } 
        else if (typeof(T) == typeof(char[])) 
        { 
         _writer.Write((char[])(object)value[i]); 
        } 
        else 
        { 
         throw new ArgumentException("List type not supported"); 
        } 

        break; 
      } 
     } 
Các vấn đề liên quan