2012-08-24 22 views
5

Tôi có 2 loại: BaseQuestionQuestion. Question kế thừa một số thuộc tính từ BaseQuestion. Bây giờ tôi đã tạo một API Web để tạo sẵn một BaseQuestion. Kiểu dữ liệu Question có các thuộc tính bổ sung mà tôi không muốn cung cấp. Tôi có một phương thức truy xuất số Question và kế hoạch ban đầu của tôi là hoàn toàn đưa nó lên BaseQuestion. Tôi nghĩ rằng nó sẽ mất tất cả các thuộc tính bổ sung mà tôi không muốn truy cập và tôi có thể trả lại nó. Vâng, nó không. Đây là những gì tôi làm:C#: Superclass vẫn có thông tin lớp con sau upcast

Question q = allQuestions[0]; 
BaseQuestion bq = q; 
string type = bq.GetType().ToString(); 

Loại bq vẫn là "Câu hỏi". Tôi không thể truy cập vào các thuộc tính BaseQuestion, nhưng tôi vẫn có thể nhìn thấy chúng trong trình gỡ rối và chúng nằm trong đầu ra JSON mà tôi gửi cho máy khách.

Bất kỳ ý tưởng nào về cách tôi có thể "buộc" bq phải thuộc loại BaseQuestion và không có bất kỳ thuộc tính nào được xác định trong lớp con?

+0

Các loại bq biến là BaseQuestion. Kiểu thời gian chạy của đối tượng mà bq là Câu hỏi. Không chắc chắn ý bạn là gì bởi "force bq to type BaseQuestion".Bạn sẽ chỉ có thể truy cập vào các thành viên BaseQuestion thông qua biến bq. – lesscode

+1

Tôi nghĩ rằng sự nhầm lẫn của bạn không hiểu rằng những gì bạn đã đưa ra là ** tài liệu tham khảo ** cho các đối tượng trong bộ nhớ. –

+0

Simon, điểm tốt. Sau đó, hãy để tôi rephrase: Làm thế nào tôi có thể tạo một đối tượng mới của loại Câu hỏi và tự động sao chép tất cả các giá trị tài sản? Bởi tự động tôi có nghĩa là tôi không ** muốn ** thực hiện nó. IMHO kịch bản này không phải là hoàn toàn duy nhất cho tình hình của tôi và nên được bao phủ bởi .NET. – Jan

Trả lời

11

Việc tạo kiểu không thay đổi bản chất của đối tượng, nó chỉ thay đổi chế độ xem của đối tượng. Khi bạn gõ vào kiểu cơ sở, bạn đang nhìn vào đối tượng thông qua một bộ lọc chỉ có thể thấy các thành viên được định nghĩa trên kiểu cơ sở, bất kể điều gì khác được định nghĩa trong đối tượng thực tế.

Khi bạn trả về một đối tượng từ một cuộc gọi dịch vụ web, nó là đối tượng thực tế sẽ được tuần tự hóa và gửi lại qua dây - tất cả các thành viên có thể tuần tự hóa của nó.

Một kỹ thuật bạn có thể sử dụng để ngăn chặn các thành viên của lớp câu hỏi bắt nguồn được trả lại cho người gọi API là để loại bỏ việc tuần tự hóa các thành viên được khai báo trong lớp câu hỏi. Có một số hệ thống con tuần tự hóa trong .NET, nhưng nếu bạn đang sử dụng XmlSerialization, bạn sẽ trang trí các thành viên được khai báo trong lớp Question với các thuộc tính [XmlIgnore] để ngăn chúng không được tuần tự hóa bởi XmlSerialization. Nếu bạn đang sử dụng một hệ thống con serialization khác nhau, bạn sẽ cần phải tìm ra tương tự của điều này trong hệ thống đó.

Một khả năng khác là xác định hợp đồng giao diện cho (các) dịch vụ API web của bạn. Lớp BaseQuestion và Question của bạn sẽ thực hiện một hoặc nhiều giao diện hợp đồng. Tôi tin rằng điều này sẽ giới hạn việc tuần tự hóa thành chỉ các thuộc tính được định nghĩa trong giao diện hợp đồng, bất kể đối tượng thực tế là gì.

Nếu thất bại, giải pháp brute force là xây dựng một thể hiện của BaseQuestion của bạn trong một temp, sao chép các thuộc tính liên quan từ đối tượng Question thực tế đến đối tượng tạm thời và trả về đối tượng temp. Điều này là thô lỗ và thô lỗ và phải có một cách tốt hơn, nhưng nó sẽ hoạt động.

+0

Tôi không thể thay đổi các loại Câu hỏi/Câu hỏi cơ sở vì Web API không phải là người dùng duy nhất của họ. Tôi hoàn toàn đồng ý về phần "có được một cách tốt hơn", và tôi đã tìm kiếm khắp nơi nhưng lại trống rỗng. Tôi nghĩ sự thất vọng của tôi đủ lớn để tạo ra một công cụ chuyển đổi rõ ràng. Nhưng cảm ơn vì sự giúp đỡ! – Jan

+0

Hầu hết câu trả lời này là chính xác, ngoại trừ phần giới hạn tuần tự hóa dựa trên kế thừa giao diện. Phần đó không hoạt động vì nó không thay đổi đối tượng gốc. Tôi muốn nó làm việc như vậy mặc dù: ( –

+0

Thay vì tạo ra một "giao diện hợp đồng", tạo ra một "mô hình hợp đồng" của bất cứ điều gì bạn muốn serialize và deserialize. Viết chức năng chuyển đổi hoặc sử dụng một thư viện như [AutoMapper] (https: // github.com/AutoMapper/AutoMapper) để chuyển đổi mô hình "đầy đủ" của bạn thành phiên bản thu nhỏ chỉ chứa các thuộc tính bạn muốn sắp xếp theo thứ tự – MarioDS

1

Việc tạo kiểu chữ chỉ thay đổi loại tham chiếu đến đối tượng, chứ không phải chính đối tượng đó.

Gọi .GetType() trên phiên bản Question sẽ luôn trả về loại Question bất kể loại biến tham chiếu đến nó.

Nếu bạn muốn loại cơ sở thì bạn cần phải gọi thuộc tính .BaseType trên loại.

Vì vậy, một cái gì đó như thế này:

string type = q.GetType().BaseType.ToString(); 
+0

Đó chỉ là để hiển thị ý tôi. Tôi cần có một đối tượng _only_ chứa Các thuộc tính của lớp cơ sở – Jan

+0

Đó không phải là loại đúc cho 'BaseQuestion' sẽ cung cấp cho bạn? – Enigmativity

+0

Đó là những gì tôi nghĩ, nhưng rõ ràng là không. Tôi không thay đổi đối tượng, tôi chỉ thay đổi container tôi lưu trữ Các thuộc tính của lớp con vẫn còn đó và sẽ được serialized – Jan

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