C# 无法将COM对象强制转换为类类型
我正在制作一个图书馆管理软件。我已经将数据库的管理分离到一个单独的c#库“DataAccessLibrary”。它包含DataAccess.cs:C# 无法将COM对象强制转换为类类型,c#,exception,uwp,com,runtimeexception,C#,Exception,Uwp,Com,Runtimeexception,我正在制作一个图书馆管理软件。我已经将数据库的管理分离到一个单独的c#库“DataAccessLibrary”。它包含DataAccess.cs: public static event MyDelegate Event_AddBook; public static void InitializeDatabase() { using (SqliteConnection db = new SqliteConnection("Filename=MyBooks.db"
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;
}
}
事件“event\u 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\u View.GridView\u AddBook()行抛出此异常:
System.InvalidCastException
HResult=0x80004002
Message=无法将类型为“System.Collections.Specialized.NotifyCollectionChangedEventHandler”的COM对象强制转换为类型为“System.Collections.Specialized.NotifyCollectionChangedEventHandler”的类。表示COM组件的类型实例不能转换为不表示COM组件的类型;但是,只要底层COM组件支持对接口IID的QueryInterface调用,就可以将它们转换为接口。
Source=System.Private.CoreLib
堆栈跟踪:
位于System.StubHelpers.StubHelpers.GetCOMIPFromRCW_WinRTDelegate(对象objSrc、IntPtr pCPCMD、IntPtr和ppTarget)
位于System.Collections.Specialized.NotifyCollectionChangedEventHandler.Invoke(对象发送方,NotifyCollectionChangedEventArgs e)
位于System.Collections.ObjectModel.ObservableCollection1.OnCollectionChanged(NotifyCollectionChangedEventArgs e)
位于System.Collections.ObjectModel.ObservableCollection
1.InsertItem(Int32索引,T项)
位于System.Collections.ObjectModel.Collection`1.Add(T项)
在C:\Users\Hemil\source\repos\Bookshelf\Bookshelf\YourBooks\u View.xaml.cs中的Bookshelf.YourBooks\u View.GridView\u AddBook(Book Book Book Book)中
在C:\Users\Hemil\source\repos\Bookshelf\DataAccessLibrary\DataAccess.cs中的DataAccessLibrary.DataAccess.AddBook(Book Book Book)中:第44行
在C:\Users\Hemil\source\repos\Bookshelf\Bookshelf\NewBook\u View.xaml.cs中的Bookshelf.NewBook\u View.d\u 3.MoveNext()中
我不知道这是什么意思。是否有办法解决此问题,或者是否有办法以其他方式通知视图
我的c不太好。请原谅我的任何错误或愚蠢的问题
编辑:我正在使用Microsoft.Data.Sqlite容器中提供的Sqlite数据库
编辑:我遵循了本教程:。我的目标是最新的Windows 10,因此我的应用程序中没有包含Sqlite
编辑:我将整个源代码上传到gitlab上的公共存储库,如下所示:
编辑:我想我也应该包括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();
}
}
public类booksview模型
{
私人可观察收集书籍{get;set;}
公开收集书籍
{
获取{返回this.books;}
设置
{
这就是价值;
}
}
公共图书视图模型()
{
books=DataAccess.GetBooks();
}
}
您试图添加到集合中的图书对象可能已附加到数据库,当您对数据库执行操作时,请确保处置其上下文(这取决于您使用的数据库提供程序)
因此,要解决此问题,您可以尝试将book对象复制到新实例,并将其放入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);
}
出现此问题的原因是您从新视图的线程更新了主视图的
ViewModel
。单击Add
按钮时,会触发AddBook
事件,这是在新视图的线程上,但会在YourBooks\u视图
类中更新主视图的ViewModel
。您应该使用该方法为新视图安排UI线程上的工作
因此,只需使用方法更改GridView\u AddBook
方法的代码,以调度UI线程上的工作,从而添加新的Book
对象
以下是GridView\u AddBook
方法的修改代码:
private async void GridView_AddBook(Book book)
{
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
ViewModel.Books.Add(book);
});
}
这听起来有点奇怪,但是:你能试着把投掷线用一个任务包起来吗?运行block?我没有得到u@TheTanic。你能说明你的意思吗?把代码行包装起来,这会在一个新任务中抛出错误。运行块,这样在另一个任务中执行。我多次遇到这个错误,这帮我解决了!或者专门使用UI Dispatcher!我还没有使用电脑,所以我无法在第一时间帮你编写代码moment@TheTanic,这就是我所做的:
Task.Run(()=>ViewModel.Books.Add(book))代码>。它给出了以下错误:System.Runtime.InteropServices.COMException HResult=0x8001010E Message=调用接口的应用程序为另一个线程封送。(来自HRESULT的异常:0x8001010E(RPC_E_错误_线程))
我今天尝试了它,您需要调度程序线程。。。我不知道需要哪一个。请您澄清一下您使用的是哪家数据库提供商,好吗?给我们看一些你如何访问数据库的代码?我更新了问题。你还有什么疑问吗?在你的代码中,你已经注释了//不必要的东西,我认为这是你访问数据库的代码,所以重要的是要看到,我只是想确保你正在处理你的dbcontext或包装在一个using语句中?我在问题中添加了一些代码。是的,他们都有一个using语句你的代码看起来很好,在这种情况下似乎出现了一些wierd错误,
private async void GridView_AddBook(Book book)
{
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
ViewModel.Books.Add(book);
});
}