MvxException: не удалось инициализировать ViewModel для типа x из локатора - PullRequest
0 голосов
/ 21 июня 2019

Вызов экспертов Xamarin и MvvmCross. Я пытался отладить эту ошибку часами MvvmCross.Exceptions.MvxException: Failed to construct and initialize ViewModel for type TestApp.Core.ViewModels.IngredientsViewModel from locator MvxDefaultViewModelLocator. Я нашел фрагмент кода, который на самом деле вызывает эту ошибку, и это связано с извлечением данных из базы данных с использованием EFCore sqlite.

Я впервые использую его для мобильного приложения, поэтому, может быть, вы заметите что-то, чего я не могу. Ниже приведена вся информация, которую я считаю адекватной, пожалуйста, дайте мне знать, если потребуется больше! Я надеюсь, что решение помогает другим. Обратите внимание, когда я комментирую GetIngredients Я не получаю ошибку выше.

Файл моего приложения в Core / Shared проекте

public class AppCore : MvxApplication
{
    public override void Initialize()
    {
        Mvx.IoCProvider.RegisterType<TestContext>();
        Mvx.IoCProvider.RegisterType<IIngredientRepository, IngredientRepository>();
        RegisterAppStart<IngredientsViewModel>();
    }
}

Мой DbContext

public class TestContext : DbContext
{
    public TestContext() : base()
    {
    }
    private const string _databaseName = "Test.db";
    public DbSet<Ingredient> Ingredients { get; set; }    
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        string databasePath;
        switch (Device.RuntimePlatform)
        {
            case Device.iOS:
                SQLitePCL.Batteries_V2.Init();
                databasePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "..", "Library", _databaseName); ;
                break;
            case Device.Android:
                databasePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal), _databaseName);
                break;
            default:
                throw new NotImplementedException("Platform not supported");
        }
        optionsBuilder.UseSqlite($"Filename={databasePath}");
    }
}

Хранилища

public interface IRepository<TEntity> where TEntity : class
{
        IEnumerable<TEntity> GetAll();
}

public class Repository<TEntity> : IRepository<TEntity> where TEntity : class
{
    protected readonly TestContext Context;
    public Repository(TestContext context)
    {
        Context = context;
    }

    public IEnumerable<TEntity> GetAll()
    {
        return Context.Set<TEntity>().ToList(); //after this line error is thrown
    }
}

public interface IIngredientRepository : IRepository<Ingredient> {}
public class IngredientRepository : Repository<Ingredient>, IIngredientRepository
{
    public IngredientRepository(TestContext testContext) : base(testContext)
    { }
}

Моя ViewModel

public class IngredientsViewModel : BaseViewModel
{
    private IIngredientRepository IngredientRepository { get; set; }

    public IngredientsViewModel(IIngredientRepository ingredientRepository)
    {
        IngredientRepository = ingredientRepository;
        GetIngredients(); //when commented out, the view loads fine
    }

    private void GetIngredients()
    {
        var ingredients = IngredientRepository.GetAll();
        Ingredients = new MvxObservableCollection<Ingredient>(ingredients);
    }

    private MvxObservableCollection<Ingredient> _ingredients;
    public MvxObservableCollection<Ingredient> Ingredients
    {
        get => _ingredients;
        set { SetProperty(ref _ingredients, value); }
    }
}

1 Ответ

1 голос
/ 21 июня 2019

В вашем TestContext.cs попробуйте добавить следующую строку в конструктор:

Database.EnsureCreated(); //returns boolean which could be used for some check if needed

А также, я бы предложил переопределить OnModelCreating как:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
        base.OnModelCreating(modelBuilder);

        //creating tables according to UML
        modelBuilder.Entity<Ingredient>();

        //add one for each table
}

Если это не помогает, попробуйте проверить InnerException или выполнить отладку шаг за шагом.

...