Каков наилучший способ заполнить привязанное к данным свойство из асинхронного метода? - PullRequest
0 голосов
/ 12 февраля 2019

У меня есть простое требование, которого я пытаюсь достичь.В основном у меня есть представление, которое заполняется списком предприятий.Свойство для списка предприятий воплощено в моем классе viewmodel, который, в свою очередь, связан с представлением.Это простое приложение MVC со списком предприятий.

Однако проблема, с которой я столкнулся, заключается в том, что я получаю список предприятий для другого класса, который является зависимостью от модели представления и в основном похож на хранилище, которое я называю BusinessService.Занятый сервис состоит из асинхронных методов, и это дилемма, которая возникает у меня, когда мой вызов вызывается из Ctor-объекта viewModel или метода получения свойства.Призыв к базе данных EF также асинхронен в пределах бизнес-службы, и я не уверен, каков правильный подход для этого.Пожалуйста, смотрите код ниже:

ViewModel:

    #region Ctor

    public BusinessListViewModel(IBusinessService businessService, IStringBuilder builder)
    {
        _businessService = businessService;
        _builder = builder;

        InitBusinesses().Wait(); //OPTION 1
    }

    #endregion

    #region Properties

    public IEnumerable<BusinessViewModel> _businesses;
    public IEnumerable<BusinessViewModel> Businesses
    {
        get
        {
            if (_businesses == null)
            {
                InitBusinesses().Wait(); //OPTION 2
            }
            return _businesses;
        }
        set => _businesses = value;
    }

    private async Task InitBusinesses()
    {
        var response = await _businessService.Get();
        Businesses = response.IsSuccessful 
                            ? response.Data.Select(p => new BusinessViewModel(_builder, p)) 
                            : new List<BusinessViewModel>();
    }

БИЗНЕС-СЕРВИС:

    #region Service Methods

    public async Task<Response<IEnumerable<Models.Business>>> Get()
    {
        var data = await Db.Businesses.ToListAsync();
        return new Response<IEnumerable<Models.Business>>
        {
            IsSuccessful = true,
            Message = "Successful",
            Data = Mapper.Map<List<Models.Business>>(data)
        };
    }

Пожалуйста, можете ли вы посоветовать лучший шаблон и правильный способ сделать это, яуже знаю, что это неправильно> Спасибо

Ответы [ 2 ]

0 голосов
/ 13 февраля 2019

Я написал статью на эту тему .

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

Более правильное решение - синхронно инициализировать в загрузкусостояние (сообщение «Загрузка ...», прядильщик и т. д.), а также запуск асинхронной операции.Затем, когда операция завершится, обновит пользовательский интерфейс с фактическими данными.

0 голосов
/ 12 февраля 2019

Вы должны рассмотреть возможность использования фабричного метода, который возвращает Task

private BusinessListViewModel(IBusinessService businessService, IStringBuilder builder)
{
    _businessService = businessService;
    _builder = builder;
}

public static async Task<BusinessListViewModel> Create(IBusinessService businessService, IStringBuilder builder)
{
    var instance = new BusinessListViewModel(businessService, builder)
    await InitBusiness();
    return instance;
}
...