2009-07-24 21 views
12

Điều này có khả thi không? Đây là những gì tôi đang cố gắng:ViewPage động được nhập

public ActionResult Index() 
    { 
     dynamic p = new { Name = "Test", Phone = "111-2222" }; 
     return View(p); 
    } 

Và sau đó quan điểm của tôi kế thừa từ System.Web.Mvc.ViewPage<dynamic> và cố gắng in ra Model.Name.

tôi nhận được một lỗi: '<> f__AnonymousType1.Name' là không thể tiếp cận do mức độ bảo vệ của nó

Vì vậy, về cơ bản, là những gì tôi đang cố gắng để làm chỉ là không thể? Tại sao hay tại sao không?

Cập nhật: đây là quan điểm của tôi

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<dynamic>" %> 

<asp:Content ...> 
    <%=Model.Name%> 
    <%=Model.Phone%> 
</asp:Content> 

The View constructor được xây dựng-in để khuôn khổ.

+1

Bạn có thể đăng thêm mã của mình không? Tôi muốn đặc biệt để xem các nhà xây dựng để xem – Randolpho

+1

Kiểm tra cập nhật mới nhất của tôi với một liên kết đến bài đăng blog của Phil Haack. – CoderDennis

Trả lời

7

Các loại vô danh không thể được trả về bằng một phương pháp; chúng chỉ hợp lệ trong phạm vi của phương thức mà chúng được xác định.

Bạn nên sử dụng lớp Mô hình mà trước đây bạn đã xác định và chuyển cho Chế độ xem của mình. Không có gì sai khi chuyển một lớp Model mà không có mọi trường được định nghĩa.

Cập nhật:

Tôi nghĩ rằng tôi đã sai trước. Điều này sẽ làm việc. Có lẽ vấn đề nằm trong Chế độ xem. Bạn có thể đăng thêm mã không? Đặc biệt là View và hàm tạo của nó.

Cập nhật lần thứ hai:

Ok, tôi đã sai về đi qua một loại vô danh đến một phương pháp khác để sử dụng như là một biến động - có thể được thực hiện.

Nhưng tôi cũng sai khi tin rằng những gì bạn đang cố gắng làm sẽ hoạt động. Thật không may cho bạn, nó sẽ không. Vấn đề là bạn đang sử dụng ViewPage<TModel>, sử dụng ViewDataDictionary<TModel> nội bộ. Vì chúng yêu cầu loại mạnh, bạn sẽ không thể sử dụng các đối tượng động với chúng. Cấu trúc bên trong không sử dụng động trong nội bộ và chỉ định động khi loại không thành công.

Điều cần thiết là lớp DynamicViewPage và tương ứng DynamicViewDataDictionary lớp chấp nhận object và lưu trữ nội bộ dưới dạng động. Sau đó, bạn có thể sử dụng một loại ẩn danh và chuyển nó cho Views của bạn.

Điều đó nói rằng, bạn sẽ không đạt được bất kỳ thứ gì. Bạn có thể chỉ định Chế độ xem của mình như bạn đã thực hiện (ví dụ: <%=Model.Name%>), nhưng bạn sẽ không được hưởng lợi từ việc nhập mạnh mẽ. Sẽ không có intellisense và sẽ không có loại an toàn. Bạn cũng sẽ làm tốt việc sử dụng ViewDataDictionary không được phân loại như @Dennis Palmer đề xuất.

Đây là một thử nghiệm thú vị (và, không may cho tôi, hấp thụ), nhưng tôi nghĩ, cuối cùng, điều đó sẽ không xảy ra. Khai báo một kiểu công khai và chuyển nó sang Views của bạn, hoặc sử dụng từ điển untyped.

+1

Nhưng tôi có thể truy cập các thành viên của đối tượng thông qua sự phản chiếu, đó là lý do tại sao tôi nghĩ rằng gõ động có thể hoạt động. –

+1

hmm ...và lỗi của bạn cho thấy rằng nó xảy ra từ bên trong Chế độ xem của bạn, có nghĩa là việc chuyển loại ẩn danh cho Chế độ xem hoạt động, nhưng mức bảo vệ mặc định của Tên được bảo vệ hoặc riêng tư. Và bạn không thể chỉ định mức độ bảo vệ của một loại vô danh khi bạn khai báo nó. – Randolpho

+0

OK, tôi đã đăng cập nhật. –

7

Bạn hy vọng có được lợi ích gì từ việc sử dụng loại động ở đây?

Sử dụng từ điển ViewData là cách rất dễ dàng để thêm các đối tượng/mục tùy ý vào đầu ra của chế độ xem của bạn.

Bạn không cần phản ánh để có được tên thuộc tính trong Chế độ xem của mình. Chỉ cần sử dụng ViewData.Keys để lấy bộ sưu tập tên.

Chỉnh sửa: Tôi vừa học thêm một chút về động lực bản thân và tôi nghĩ có thể bạn cần tạo lớp đối tượng động của riêng bạn kế thừa từ DynamicObject. Bạn sẽ muốn có một từ điển riêng tư trong lớp đó và sau đó ghi đè lên TrySetMemberTryGetMember.

Chỉnh sửa Bên cạnh: Tôi nghĩ một lợi thế của một ViewModel được đánh máy mạnh là bạn có thể chấp nhận nó như một tham số trong phương thức POST hành động của bạn. Khung MVC sẽ xử lý ràng buộc mô hình và trong phương thức hành động, bạn chỉ đơn giản là có một cá thể của lớp ViewModel của bạn. Tôi không nghĩ rằng bạn sẽ có lợi thế đó với một động lực ngay cả khi họ làm việc.

Chỉnh sửa kết quả: Vâng, tôi đã thử sử dụng lớp học có nguồn gốc từ DynamicObject, nhưng VS2010 gặp sự cố khi cố gắng hiển thị chế độ xem. Tôi không nhận được bất kỳ ngoại lệ, chỉ là một vụ tai nạn cứng và Visual Studio khởi động lại. Đây là mã tôi đã nghĩ ra là nguyên nhân gây ra sự cố.

Các lớp tùy chỉnh năng động:

public class DynViewModel : DynamicObject 
{ 
    private Dictionary<string, object> ViewDataBag; 
    public DynViewModel() 
    { 
     this.ViewDataBag = new Dictionary<string, object>(); 
    } 
    public override bool TrySetMember(SetMemberBinder binder, object value) 
    { 
     this.ViewDataBag[binder.Name] = value; 
     return true; 
    } 
    public override bool TryGetMember(GetMemberBinder binder, out object result) 
    { 
     result = this.ViewDataBag[binder.Name]; 
     return true; 
    } 
} 

Trong bộ điều khiển:

public ActionResult DynamicView() 
{ 
    dynamic p = new DynamicViewModel.Models.DynViewModel(); 
    p.Name = "Test"; 
    p.Phone = "111-2222"; 

    return View(p); 
} 

Quan điểm của tôi về cơ bản là giống như những gì được liệt kê trong câu hỏi:

<p>Name: <%=Model.Name %></p> 
<p>Phone: <%=Model.Phone %></p> 

My Kết luận: Điều này có thể hiệu quả, nhưng trong bản Beta 1 của VS2010 tôi không thể tìm ra lý do tại sao mã của tôi khiến Visual Studio bị lỗi. Tôi sẽ thử lại trong VS2010 Beta 2 khi nó được phát hành vì nó là một bài tập thú vị trong việc học về động lực học. Tuy nhiên, ngay cả khi điều này là để làm việc, tôi vẫn không thấy bất kỳ lợi thế hơn bằng cách sử dụng từ điển ViewData.

Phil Haack để giải cứu! Đây là bài đăng trên blog của Phil Haack có thể giúp bạn. Có vẻ như đó là những gì bạn đang tìm kiếm. Fun With Method Missing and C# 4

+0

Vâng, tôi chưa thực sự chắc chắn 100%, tôi chỉ đang thử nghiệm một chút với 4.0. Tôi đoán những gì tôi muốn thấy là khả năng sử dụng mô hình ViewModel mà không thực sự phải viết một loạt các ViewModels, nhưng tôi cũng đang cố gắng để có được một sự hiểu biết sâu hơn về gõ động trong C# là tốt. –

1

Lỗi thực tế tại đây (<>f__AnonymousType1.Name' is inaccessible due to its protection level) là kết quả của việc sử dụng các loại ẩn danh. Các loại ẩn danh hoàn toàn là internal (ít nhất là trong C#), do đó chúng chỉ có thể được truy cập bình thường từ cùng một assembly. Vì chế độ xem của bạn được biên dịch thành một cụm riêng biệt riêng lẻ khi chạy, nó không thể truy cập vào loại internal ẩn danh.

Giải pháp là chuyển các lớp cụ thể/được đặt tên làm mô hình cho chế độ xem của bạn. Bản thân chế độ xem vẫn có thể sử dụng dynamic nếu bạn muốn.

1

Trên .NET 4.0 Các kiểu ẩn danh có thể dễ dàng được chuyển đổi thành ExpandoObjects và do đó tất cả các vấn đề được cố định với chi phí của chính chuyển đổi đó. Khám phá here

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