2010-02-21 30 views
20

Tôi có một phương thức dịch vụ WCF dự kiến ​​một đối tượng và sau đó truy lục các thuộc tính của nó bằng cách sử dụng sự phản chiếu.Truyền một thể hiện kiểu ẩn danh qua WCF

Về phía khách hàng để tạo một đối tượng kiểu nặc danh

var obj = new {FirstName="John", LastName="Doe"} 

và vượt qua nó để phương pháp này. Tôi nhận được ngoại lệ:

Type '<>f__AnonymousType0`2[System.String,System.String]' cannot be serialized. 
Consider marking it with the DataContractAttribute attribute, and marking all 
of its members you want serialized with the DataMemberAttribute attribute. 
See the Microsoft .NET Framework documentation for other supported types. 

Tôi không thể đánh dấu loại hoặc thành viên của nó bằng thuộc tính tuần tự hóa vì không có loại hoặc thuộc tính nào được khai báo rõ ràng. Có cách nào để khắc phục vấn đề đó không?

Trả lời

17

Đừng làm điều này.

Đó là một nỗ lực để thông minh. Đừng. Chỉ cần khai báo kiểu dữ liệu bạn cần và sử dụng nó. Nếu bạn cần một kiểu dữ liệu lỏng lẻo hơn, chỉ cần sử dụng ánh xạ khóa-giá trị của một số loại.

Bạn sẽ mất 5 phút để viết nội dung nào đó có thể xử lý điều này. Sử dụng bất kỳ kỹ thuật như thế này sẽ chi phí cho bạn giờ gỡ lỗi tại một số điểm tương lai xuống đường.

+0

Yup, tôi đã kết thúc bằng một từ điển các đối tượng khóa – Andrey

+0

Tôi đã gặp vấn đề tương tự và đã trôi qua nửa ngày trước khi tôi nhận ra đó là một ý tưởng tồi. Không phải giờ tốt nhất của tôi. Tôi chỉ muốn hỗ trợ kyoryu với giai thoại về những gì ông đã tiên tri. – Four

1

Bạn đã có câu trả lời. Nó không thể được thực hiện.

Thực tế, bạn không thể chuyển thể hiện loại ẩn danh từ một phương thức này sang phương thức khác trong chương trình của bạn. Bạn chắc chắn không thể vượt qua chúng giữa các chương trình.

+0

thực sự, bạn có thể - bạn có thể xác định loại trả về của "đối tượng" và sau đó chỉ trả lại trường hợp loại ẩn danh của bạn. Đó là một loại vô danh, nhưng nó vẫn cuối cùng là hậu duệ của "đối tượng". Không được đề nghị, cũng không có ý định - nhưng có thể - ít nhất là trong phạm vi .NET –

+0

@marc_s: Điều này sẽ biên dịch nhưng khá vô ích, vì không có siêu dữ liệu nào được tạo cho kiểu trả về 'System.Object'. – Aaronaught

+0

@Aaronaught: Tôi chưa bao giờ nói nó có ích trong bất kỳ cách nào, hình dạng hay hình thức - chỉ có thể :-) Tôi chưa bao giờ tự làm, nhưng về mặt kỹ thuật có thể là –

2

Không, không có. Trong khi có những thủ thuật và kỹ thuật để trả về các đối tượng của một kiểu vô danh từ một phương thức, bạn không thể gửi chúng qua WCF.

WCF cần biết tất cả các loại cụ thể của nó sẽ được gửi qua, vì bạn không thực sự chỉ cần gọi một phương thức .NET. Thay vào đó, các cuộc gọi tin nhắn được chuyển đổi thành một tin nhắn serialized, và do đó, bất kỳ "điều" được thông qua một cuộc gọi WCF phải được serializable - không có ngoại lệ.

19

answers suggesting mà bạn can't use an anonymous type over WCF sai.

Nếu bạn đang sử dụng mặc định DataContractSerializer để tuần tự hóa các loại của bạn trên kênh, thì có, câu trả lời là chính xác. Điều này là do DataContractSerializer hỗ trợ các tình huống sau đây:

  1. loại đăng bằng cách sử dụng Serializable attribute
  2. loại serialized sử dụng XML Serialization
  3. loại đăng bằng cách sử dụng DataContract attribute
  4. Plain-Old-C#-Object (POCO) Serialization

Tương ứng, họ thất bại với các loại ẩn danh vì:

  1. Bạn không thể áp dụng thuộc tính cho các loại ẩn danh.
  2. Chuỗi tuần tự XML yêu cầu một hàm tạo tham số mặc định không có loại ẩn danh nào.
  3. Tương tự như 1.
  4. Tương tự như 2.

Tuy nhiên, bạn không buộc phải sử dụng các DataContractSerializer serialize tin nhắn của bạn trong WCF. Bạn có thể tạo một custom message formatter mà bạn có thể sử dụng để tự thực hiện tuần tự hóa.

Bạn gặp sự cố nếu các loại bạn gửi đi vì kết quả của yêu cầu là các loại ẩn danh. Khi bạn lấy lại kết quả, nó sẽ có một tên xác định trong một không gian tên (không phải trong một ý nghĩa .NET, nhưng theo nghĩa SOA) và bạn sẽ phải xử lý ánh xạ của kiểu cụ thể đó trở lại kiểu ẩn danh . Tuy nhiên, vì bạn không có quyền truy cập vào loại ẩn danh thực tế hoặc cách xây dựng nó trong mã (ít nhất là theo cách năng động), bạn không có lựa chọn nào khác ngoài việc chuyển nó thành một đối tượng nếu nó được trả lại cho bạn, làm cho nó trở nên vô giá trị, vì mọi người sẽ phải sử dụng những thực hành xấu như năng động (không phải là một thực hành tồi, nhưng để tránh những giới hạn trong trường hợp này, có), hoặc cast-by-example. Vì vậy, cuối cùng tôi sẽ nói rằng mặc dù chắc chắn là có thể để sắp xếp các loại vô danh và gửi chúng qua dây, tác phẩm được truyền đi thường không đáng giá.

+2

+1 cho câu trả lời đúng về mặt kỹ thuật. -1 để đề cập đến một kỹ thuật thuần khiết. Tôi lo lắng ai đó sẽ đọc điều này và bỏ qua cảnh báo "thực hành xấu" - quên tái cấu trúc, bạn cần một pháp sư. – Aaronaught

+5

Đề cập đến bất kỳ kỹ thuật nào cần được xem xét chia sẻ kiến ​​thức và không bị khinh miệt. Bên cạnh đó, ngay cả những người trừ tà cũng cần biết về ma quỷ. –

0

Như đã nói trước đây, các đối tượng phải được deserializable và do đó bạn sẽ phải xác định cấu trúc trước. Tuy nhiên, bạn có thể sử dụng thừa kế để xác định chúng, và do đó giảm đau. WCF cung cấp thuộc tính KnownType để cho phép một Service Operation nhận một đối tượng của lớp cơ sở và deserialize nó vào một đối tượng của một lớp dẫn xuất. Vì vậy, bạn sẽ vẫn chỉ có một (hoặc một vài) Hoạt động dịch vụ có thể xử lý tất cả các kịch bản của bạn.

4

Bạn có thể serialize các đối tượng vào một chuỗi JSON và gửi nó qua WCF, như vậy:

//in WCF Server 
dynamic mysentclass = new { FirstName = "John", LastName = "Doe" }; 
string jsonstring = JsonConvert.SerializeObject(mysentclass, Newtonsoft.Json.Formatting.Indented); 
//send the string through WCF 

//in WCF client 
dynamic myreceivedclass = JsonConvert.DeserializeObject<dynamic>(jsonstring); 
MessageBox.Show(myreceivedclass.FirstName.ToString() + " " + myreceivedclass.LastName.ToString()); 

Ví dụ sử dụng Json.Net, mà có thể thu được ở đây:

http://www.nuget.org/packages/Newtonsoft.Json/

Bạn cũng có thể sử dụng System.Web.Script.Serialization.JavaScriptSerializer (trong System.Web.Extensions.dll), mà không phải là mạnh mẽ như Json.Net, nhưng sẽ đủ cho các đối tượng đơn giản.

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