代码之家  ›  专栏  ›  技术社区  ›  CodingInsomnia

在我的ViewModel中使用DataServiceCollection时如何实现“可混合性”

  •  2
  • CodingInsomnia  · 技术社区  · 14 年前

    我正在研究在Silverlight客户端中使用oData端点。当然,我在做MVVM,我希望项目是好的和“可混合的”(即,在设计模式下,我必须能够干净地使用静态数据,而不是oData端点)

    现在来谈谈问题。我想在ViewModels中使用DataServiceCollection,因为它允许很好的可绑定集合,而不必过于担心BeginExecute/EndExecute等。

    现在,让我们看一些代码。我的模型界面如下所示:

    public interface ITasksModel
    {
        IQueryable<Task> Tasks { get; }
    }
    

    该接口的oData端点实现:

    public class TasksModel : ITasksModel
    {
        Uri svcUri = new Uri("http://localhost:2404/Services/TasksDataService.svc");
    
        TaskModelContainer _container;
    
        public TasksModel()
        {
            _container = new TaskModelContainer(svcUri);
        }
    
        public IQueryable<Task> Tasks
        {
            get
            {
                return _container.TaskSet;
            }
        }
    }
    

    以及“可混合”的设计时实现:

    public class DesignModeTasksModel : ITasksModel
    {
        private List<Task> _taskCollection = new List<Task>();
    
        public DesignModeTasksModel()
        {
            _taskCollection.Add(new Task() { Id = 1, Title = "Task 1" });
            _taskCollection.Add(new Task() { Id = 2, Title = "Task 2" });
            _taskCollection.Add(new Task() { Id = 3, Title = "Task 3" });
        }
    
        public IQueryable<Task> Tasks
        {
            get {
                return _taskCollection.AsQueryable();
            }
        }
    }
    

    但是,当我尝试在ViewModel构造函数中使用最后一个时:

        public TaskListViewModel(ITasksModel tasksModel)
        {
            _tasksModel = tasksModel;
    
            _tasks = new DataServiceCollection<Task>();
            _tasks.LoadAsync(_tasksModel.Tasks);
        }
    

    我有个例外:

    在DataServiceCollection上调用LoadAsync方法时,只能提供类型化DataServiceQuery对象。

    首先,如果是这样,为什么不将LoadAsync的输入参数类型化为DataServiceQuery呢?

    1 回复  |  直到 14 年前
        1
  •  1
  •   Vitek Karas MSFT    14 年前

    LoadAsync需要DataServiceQuery的原因是普通IQueryable没有定义执行查询的异步方式。该方法将IQueryable类型作为其参数的原因是,用户不必显式地将查询对象强制转换为DataServiceQuery(使代码更短),而且由于我们假设用户将尝试至少运行一次代码,因此他们会立即看到错误(如您所做)。

    LoadAsync只支持异步操作,因此需要DataServiceQuery。如果已经有了结果(无需执行异步请求),则可以调用Load方法。这是你第二个问题的答案。不必在设计时和运行时都调用LoadAsync,您可以在设计时使用Load,在运行时使用LoadAsync。但是由于跟踪限制,您可能需要以不同的方式创建DataServiceCollection。

    像这样:

    DataServiceCollection<Task> dsc;
    DataServiceQuery<Task> dsq = _tasksModel as DataServiceQuery<Task>;
    if (dsq != null)
    {
        dsc = new DataServiceCollection<Task>();
        dsc.LoadAsync(dsq);
    }
    else
    {
        dsc = new DataServiceCollection<Task>(myDataServiceContext);
        dsc.Load(_tasksModel);
        // Invoke the LoadAsyncCompleted handler here
    }
    

    如果在caling Load之前将DataServiceContext传递给构造函数,那么将跟踪实体(就像LoadAsync情况一样)。如果不需要,可以调用采用IEnumerable和TrackingMode的构造函数并关闭对它的跟踪。