Невозможно привести COM-объект к типу класса

2

Я делаю программное обеспечение для управления библиотекой. Я разделил управление базой данных на отдельную библиотеку С# DataAccessLibrary. Он содержит DataAccess.cs:

public static event MyDelegate Event_AddBook;

    public static void InitializeDatabase()
    {
        using (SqliteConnection db = new SqliteConnection("Filename=MyBooks.db"))
        {
            db.Open();

            //Not necessary
        }
    }

    public static void AddBook(Book book)
    {
        Event_AddBook.Invoke(book);

        using (SqliteConnection db = new SqliteConnection("Filename=MyBooks.db"))
        {
            db.Open();
            //Not necessary
        }            
    }

    public static ObservableCollection<Book> GetBooks()
    {
        ObservableCollection<Book> books = new ObservableCollection<Book>();

        using (SqliteConnection db = new SqliteConnection("Filename=MyBooks.db"))
        {
            db.Open();
            //Not necessary
        }

        return books;
    }
}

Когда книга добавляется в базу данных, она вызывает событие, так что мой класс MyBooks_View (который отображает книги) уведомляется о том, что книга добавлена.

(ПРИМЕЧАНИЕ. Книга добавляется в новом окне.)

В другом файле я добавляю книгу в базу данных следующим образом:

Book b = new Book
{
    Title = title,
    Author = author,
    Publisher = publisher,
    ISBN = isbn,
    Quantity = quantity.GetValueOrDefault(),
    CoverImageLocation = CoverImageUri
};

DataAccess.AddBook(b);

Событие "Event_AddBook" подписывается классом YourBooks:

public sealed partial class YourBooks_View : Page
{
    private BooksViewModel ViewModel { get; set; } = new BooksViewModel();

    public YourBooks_View()
    {
        this.InitializeComponent();
        DataAccess.Event_AddBook += new MyDelegate(this.GridView_AddBook);
    }

    private void GridView_AddBook(Book book)
    {
        ViewModel.Books.Add(book);
    }
}

Код компилируется без ошибок, но во время выполнения, когда я добавляю книгу, это исключение вызывается в строке YourBooks_View.GridView_AddBook():

System.InvalidCastException HResult = 0x80004002 Сообщение = Невозможно передать COM-объект типа "System.Collections.Specialized.NotifyCollectionChangedEventHandler" в тип класса "System.Collections.Specialized.NotifyCollectionChangedEventHandler". Экземпляры типов, представляющих COM-компоненты, нельзя отбрасывать типам, которые не представляют COM-компоненты; однако они могут быть переданы в интерфейсы до тех пор, пока базовый COM-компонент поддерживает вызовы QueryInterface для IID интерфейса. Source = System.Private.CoreLib StackTrace: at System.StubHelpers.StubHelpers.GetCOMIPFromRCW_WinRTDelegate (Object objSrc, IntPtr pCPCMD, IntPtr & ppTarget) в System.Collections.Specialized.NotifyCollectionChangedEventHandler.Invoke(Object sender, NotifyCollectionChangedEventArgs e) в System.Collections.ObjectModel.ObservableCollection 1.OnCollectionChanged(NotifyCollectionChangedEventArgs e) at System.Collections.ObjectModel.ObservableCollection 1.InsertItem (индекс Int32, элемент T) в System.Collections.ObjectModel.Collection'1.Add (элемент T) в Bookshelf.YourBooks_View.GridView_AddBook ( Book book) в C:\Users\Hemil\source\repos\Bookshelf\Bookshelf\YourBooks_View.xaml.cs: строка 54 в DataAccessLibrary.DataAccess.AddBook (книга) в C:\Users\Hemil\source\repos\Bookshelf\DataAccessLibrary\DataAccess.cs: строка 44 в Bookshelf.NewBook_View.d__3.MoveNext() в C:\Users\Hemil\source\repos\Bookshelf\Bookshelf\NewBook_View.xaml.cs: строка 137

Я не знаю, что это значит. Есть ли способ решить эту проблему или есть способ уведомить мнение каким-то другим способом.

Я не так хорош в С#. Прости меня за любую ошибку или глупый вопрос.

EDIT: Я использую базу данных Sqlite, как показано в контейнере Microsoft.Data.Sqlite.

EDIT: Я следовал этому руководству: https://docs.microsoft.com/en-us/windows/uwp/data-access/sqlite-databases. Я нацелен на последнюю версию Windows 10, поэтому я не включил Sqlite с моим приложением

EDIT: я загрузил весь исходный код в общедоступный репозиторий на gitlab: https://gitlab.com/rahem027/bookshelf2

EDIT: Я думаю, что я должен был включить исходный код BookViewModel. Ну вот, вот:

public class BooksViewModel
{
    private ObservableCollection<Book> books { get; set; }

    public ObservableCollection<Book> Books
    {
        get { return this.books; }

        set
        {
            this.books = value;
        }
    }


    public BooksViewModel()
    {
        books = DataAccess.GetBooks();
    }
}
  • 0
    Это звучит немного странно, но: Можете ли вы попытаться обернуть бросающую линию в блоке Task.Run?
  • 0
    Я не получил тебя @TheTanic. Можешь показать, что ты имеешь в виду?
Показать ещё 3 комментария
Теги:
exception
uwp
com
runtimeexception

2 ответа

3
Лучший ответ

Причина, по которой возникает эта проблема, заключается в том, что вы обновляете Main View ViewModel из потока New View. Когда вы нажмете кнопку " Add, событие " AddBook, это будет в потоке "Новый вид", но вы обновите Main View ViewModel в классе YourBooks_View. Вы должны использовать метод CoreDispatcher.RunAsync, чтобы запланировать работу над потоком пользовательского интерфейса для нового представления.

Поэтому просто измените свой код вашего метода GridView_AddBook с помощью метода CoreDispatcher.RunAsync, чтобы запланировать работу над потоком пользовательского интерфейса, чтобы добавить новый объект Book.

Вот модифицированный код метода GridView_AddBook:

private async void GridView_AddBook(Book book)
{
    await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
    {
        ViewModel.Books.Add(book);
    });
}
0

объект книги, который вы пытаетесь добавить в коллекцию, может быть привязан к базе данных. Когда вы выполняете операцию с базой данных, обязательно удаляйте ее контекст (который зависит от того, какой поставщик db вы используете).

Поэтому, чтобы обойти это, вы можете просто попытаться скопировать объект книги в новый экземпляр и поместить его в свою коллекцию ViewModel так:

private void GridView_AddBook(Book book)
{
    Book b = new Book
    {
        Title = book.title,
        Author = book.author,
        Publisher = book.publisher,
        ISBN = book.isbn,
        Quantity = book.quantity.GetValueOrDefault(),
        CoverImageLocation = book.CoverImageUri
    };
    ViewModel.Books.Add(b);
}
  • 0
    Показывает ту же ошибку.
  • 0
    не могли бы вы уточнить, какого поставщика баз данных вы используете? и покажите нам некоторый код того, как вы обращаетесь к базе данных?
Показать ещё 6 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню