Как реорганизовать вызовы службы данных RIA на уровень обслуживания? - PullRequest
2 голосов
/ 29 августа 2011

Я борюсь с некоторыми базовыми принципами проектирования MVVM в приложении Silverlight 4 с использованием служб и объектов RIA. Вот основной сценарий, который работает нормально:

DataViewModel.cs

public DataViewModel : NotificationObject

    private DataDomainContext _dataContext;

    public DataViewModel()  
    {
       _dataContext = new DataDomainContext();

       if (!DesignerProperties.IsInDesignTool)
       {
         Data = _dataContext.Data;
         dataContext.Load(_dataContext.GetDataQuery(), null, null);
       }
    }

    private IEnumerable<DataEntity> _data;
    public IEnumerable<DataEntity> Data   // INPC property
    {
        get { return _data; }
        set
        {
            if (value != _data)
            {
                _data = value;
                PropertyChanged(this, new PropertyChangedEventArgs("Data"));
            }
        }
    }
}

DataGrid, на мой взгляд, связан в одностороннем порядке с DataViewModel.Data, а DataDomainContext - это контекст домена RIA, предоставляемый после компиляции доменной службы для объекта DataEntity.

Я хочу отделить модель вида от DAL. Мне нужен класс DataService, который позаботится о том, чтобы запрашивать данные в контексте домена:

public DataViewModel : NotificationObject

    private DataService _dataService;

    public DataViewModel(DataService dataService)  
    {
       _dataService = dataService;

       if (!DesignerProperties.IsInDesignTool)
       {
         Data = _dataService.Data;
         _dataService.GetData();
       }
    }

    ...
}

Тем не менее, я не могу понять это правильно. Это легко сделать? Я не проектировал службу данных с обратными вызовами раньше. Я попытался связать свойства данных через INPC между тремя классами, но DataGrid в пользовательском интерфейсе был пустым. Я также хотел бы преобразовать в коллекцию нового типа, DataDto, чтобы мой уровень представления не был связан с бэкэндом. Я попытался что-то подобное без удачи:

DataService.cs

public DataService : INotifyPropertyChanged
{
   public DataService()
   {
     _dataContext = new DataDomainContext();
   }

   public event PropertyChangedEventHandler PropertyChanged;

   public void GetData()
   {
     DataEntities = _domainContext.Data;
     _dataContext.Load(_dataContext.GetDataQuery(), FinishedLoading, null);
   }

   private void FinishedLoading(...)
   {
      Data = DataEntities.Select(de => new DataDto(de));
   }

   public IEnumerable<DataDto> Data { ... }  // INPC property, used for binding in ViewModel

   public IEnumerable<DataEntity> DataEntities { ... }  // INPC property

   ...
}

Я даже на правильном пути здесь? Я что-то упускаю из-за высокого уровня или у меня просто нет деталей?

Edit:

Я смог со временем разобраться. Ответ включает передачу обратного вызова в вызов службы данных / хранилища через действие <>. Тип возврата вызова на самом деле void, и для доставки результатов используются аргументы событий. Я рад опубликовать рабочий код, если кому-то интересно, просто оставьте заявку в комментариях.

1 Ответ

2 голосов
/ 30 августа 2011

Я думаю, что вы на правильном пути, но , на мой взгляд ваше решение не является правильным, если вы на самом деле пытаетесь отделить модель представления от службы данных. Я работаю над приложением, очень похожим на это прямо сейчас. У разных людей разные представления о mvvm, и это только мой личный подход, который я усвоил методом проб и ошибок (с использованием visual studio):

Начните с создания проекта приложения silverlight и размещения его в .web проекте. Проект Silverlight будет содержать представления и модели просмотра. Модели представлений должны содержать ваши модели, а не данные службы! Тем не менее, модели представлений должны иметь экземпляр вашей службы данных для установки моделей. Где моя служба данных? Я рад, что ты спросил :). Добавьте еще один проект, библиотеку классов служб WCF RIA. Это на самом деле два проекта, DLL-служба ria (на стороне сервера) и соответствующая dll Silverlight (на стороне клиента). Вы можете добавить свою платформу сущностей или другой код доступа к базе данных на стороне сервера. После этого добавьте службу домена в проект на стороне сервера. Сначала создайте его (важно), а затем перейдите к клиентской DLL-службе ria и создайте класс службы данных с вашими методами для службы данных, например:

public void GetData( string filter, Action<LoadOperation<MyEntityType>> callback )
    {
        var q = from e in _context.GetDataQuery()
                where e.SomeField.Contains(filter)
                select e;
        _context.Load(q, LoadBehavior.RefreshCurrent, callback, null);
    }

В вашей службе данных не должно быть изменено свойство Inotify, потому что это роль моделей представлений! Ссылка на dll на стороне клиента службы ria в вашем проекте silverlight, а также на dll на стороне сервера обслуживания ria в вашем проекте веб-хостинга модель представления должна вызывать эту службу данных следующим образом:

IEnumerable<MyEnityType> Model {get;set;}
//NOTE: add notify property changed in setter!

private void GetData()
{
    _myDataService.GetData( _filter, loadOperation =>
            {
                if ( loadOperation.HasError )
                    HandleError(loadOperation.Error);    
                Model = loadOperation.Entities;
            } );
}

Вы можете сделать еще один шаг вперед и внедрить интерфейс для службы данных, если вы действительно хотите разделить их. Использование этого подхода позволяет повторно использовать вашу службу данных (в случае, если вам нужно приложение для настольного компьютера или приложение для телефона), я надеюсь, что это поможет разобраться!

...