我一直在用 C# 编组对象(从二进制文件流中读取),这些对象是使用C# 的 COM 互操作功能从非托管 C++ 结构写入的。我的目标是通过实现 INotifyPropertyChanged 接口使这些对象可用于数据绑定。
问题是,实现 INotifyPropertyChanged 不可避免地将属性更改事件公开为公共类成员。这被编组服务识别并视为 4 字节结构成员,从而在编组操作期间更改二进制布局。
这是对问题的简单演示。考虑这个C++ 结构:
struct Struct
{
int SomeMember; // example member
}
以及结构的这个C# 类改编:
[StructLayout(LayoutKind.Sequential)] // required for class marshalling
public class CppStruct
{
private int someMember; // encapsuled properties are recognized during marshalling
public int SomeMember { get => someMember; set => someMember = value; } // example member
}
以及具有实现的 INotifyPropertyChanged 接口的同一个类:
[StructLayout(LayoutKind.Sequential)] // required for class marshalling
public class CppStructNotifyPropertyChanged : INotifyPropertyChanged
{
private int someMember; // encapsuled properties are recognized during marshalling
public int SomeMember
{
get => someMember;
set
{
someMember = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(SomeMember)));
}
}
public event PropertyChangedEventHandler PropertyChanged; // required by INotifyPropertyChanged implementation
}
然后System.Runtime.InteropServices.Marshal.SizeOf< CppStruct >()
给出4,这是该结构的二进制布局的正确大小,但给出8。这表明该成员被自动视为 4 字节类型。System.Runtime.InteropServices.Marshal.SizeOf<
CppStructNotifyPropertyChanged
>()
PropertyChanged
我已经尝试找到一种方法来隐藏事件成员以进行编组,但这似乎是不可能的。任何类型的与继承相关的解决方案似乎都不适用,因为 INotifyPropertyChanged 事件覆盖所有成员,它们需要在分配时在所有(包括基类)成员上调用。我还考虑为该类编写一个自定义序列化程序,它会忽略事件成员或引入允许隐藏成员的自定义属性,但这对我来说是最坏的选择。如果可能的话,我想继续使用默认的编组功能。
有什么办法可以做到这一点?
值得一提的是,我无法访问或控制 C++ 端写入和读取这些结构,我也看不出有什么原因。将任何形式的事件对象放在文件上都是没有用的。此外,我将 .NET Framework 4.7.2 与 Visual Studio 2017 一起使用。