2011-06-29 23 views
10

Tôi khá mới đối với MVVM, vì vậy hãy tha thứ cho tôi nếu vấn đề này có một giải pháp nổi tiếng.Không chặn các thuộc tính lười biếng tải trong mô hình MVVM

Chúng tôi đang xây dựng một loạt các lớp mô hình có một số thuộc tính cốt lõi được tải lên phía trước, cũng như một số thuộc tính bổ sung có thể được tải theo yêu cầu bằng cách thực hiện cuộc gọi API web (cập nhật: để làm rõ, nó sẽ là một cuộc gọi API web cho mỗi thuộc tính được tải nhanh).

Thay vì có nhiều mô hình, có vẻ như hợp lý để có một mô hình duy nhất có logic tải lười trong đó. Tuy nhiên, có vẻ như các thuộc tính được nạp lười không nên chặn khi được truy cập, để khi View liên kết với ViewModel và nó liên kết với Model, chúng ta không chặn luồng UI.

Như vậy, tôi đã nghĩ đến một mẫu gì đó khi một thuộc tính lười biếng trên Mô hình được truy cập bắt đầu tìm nạp không đồng bộ và sau đó trả về giá trị mặc định ngay lập tức (ví dụ: null). Khi tìm nạp không đồng bộ hoàn thành, nó sẽ nâng cao sự kiện PropertyChanged để ViewModel/View có thể liên kết lại với giá trị được tìm nạp.

Tôi đã thử này ra và nó có vẻ làm việc khá độc đáo, nhưng đã tự hỏi:

  1. Có những cạm bẫy để phương pháp này mà tôi đã không phát hiện ra về, nhưng sẽ chạy vào như ứng dụng tăng độ phức tạp?
  2. Có giải pháp hiện tại cho vấn đề này được tích hợp trong khung công tác hoặc được sử dụng rộng rãi như là một phần của khuôn khổ của bên thứ ba không?
+0

Vấn đề có thể xảy ra, là bạn cần lắng nghe sự kiện PropertyChanged trên tất cả các trình tải xuống lười biếng này, nghĩa là nếu bạn có thuộc tính hoặc chức năng dựa trên nhiều bộ tải này, nó sẽ phải chờ tất cả các trình tải nó dựa vào để hoàn thành trước khi thực thi mã riêng của nó. Điều này có thể dẫn đến việc phải viết rất nhiều logic mà nếu không có thể đã được viết như một cuộc gọi đơn luồng kết hợp tìm nạp các bộ tải lười "đồng bộ" trong chủ đề riêng biệt đó. –

+0

@Timothy - Tốt. Tôi đã có một suy nghĩ về điều đó, và cảm giác của tôi là do bản chất của dữ liệu được tải một cách lười biếng, nó không chắc rằng bất cứ điều gì sẽ phụ thuộc vào nhiều dữ liệu lười biếng. Có khả năng là nhiều thứ sẽ phụ thuộc vào một mẩu dữ liệu lười biếng, nhưng tôi không nghĩ rằng đó là một vấn đề. –

+0

Tôi sử dụng cách tiếp cận chính xác mà bạn mô tả ở trên và nó hoạt động rất tốt. – Jeff

Trả lời

6

Tôi đã làm điều tương tự trong quá khứ và một điều tôi quên là bạn không thể gọi tài sản không đồng bộ của bạn thông qua bất kỳ loại mã nào phía sau và mong đợi nó có giá trị. Vì vậy, nếu tôi lười tải danh sách Customer.Products, tôi không thể tham chiếu Customer.Products.Count trong mã sau bởi vì lần đầu tiên được gọi là giá trị NULL hoặc 0 (tùy thuộc vào việc tôi tạo bộ sưu tập trống hay không)

Ngoài ra, nó hoạt động tốt cho các ràng buộc. Tôi đã sử dụng thư viện Async CTP để thực hiện cuộc gọi không đồng bộ của mình, điều mà tôi thấy là tuyệt đối tuyệt vời cho một thứ như thế này.

public ObservableCollection<Products> Products 
{ 
    get 
    { 
     if (_products == null) 
      LoadProductsAsync(); 

     return _products; 
    } 
    set { ... } 
} 

private async void LoadProductsAsync() 
{ 
    Products = await DAL.LoadProducts(CustomerId); 
} 

Cập nhật

Tôi nhớ một điều tôi có vấn đề với dữ liệu đã thực sự là NULL. Nếu Customer.Products thực sự trả về giá trị NULL từ máy chủ, tôi cần biết rằng phương thức async đã chạy đúng và giá trị thực tế là null để nó không chạy lại phương thức async.

Tôi cũng không muốn phương thức async chạy hai lần nếu ai đó gọi phương thức Get lần thứ 2 trước khi cuộc gọi async đầu tiên hoàn tất.

Tôi đã giải quyết điều này tại thời điểm bằng cách có thuộc tính Is[AsyncPropertyName]Loading/ed cho mọi thuộc tính không đồng bộ và đặt thành đúng trong cuộc gọi async đầu tiên, nhưng tôi thực sự không hài lòng về việc phải tạo thuộc tính bổ sung cho tất cả thuộc tính không đồng bộ.

+0

* (Thêm đánh dấu cú pháp) * –

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