Есть ли способ реализовать INotifyPropertyChanged на объектах, которые взаимодействуют маршалинг без влияния на двоичный макет? - PullRequest
0 голосов
/ 06 марта 2020

Я выполнял маршалинг объектов в C# (считанных из потока двоичных файлов), которые написаны из неуправляемых структур C ++ с использованием C# функций взаимодействия COM . Моя цель состоит в том, чтобы сделать эти объекты доступными для привязки данных путем реализации интерфейса INotifyPropertyChanged .

Проблема заключается в том, что реализация INotifyPropertyChanged неизбежно сопровождается представлением события, измененного свойством, как класса publi c член. Службы маршаллинга распознают и обрабатывают его как 4-байтовый элемент структуры, тем самым изменяя двоичную структуру во время операций маршаллинга.

Это упрощенная c демонстрация проблемы. Рассмотрим эту C ++ struct :

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 , что является правильным размером двоичного макета этой структуры, но System.Runtime.InteropServices.Marshal.SizeOf<CppStructNotifyPropertyChanged>() дает 8 . Это показывает, что элемент PropertyChanged автоматически обрабатывается как 4-байтовый тип.

Я пытался найти способ скрыть элемент события для маршалинга, но это просто не Кажется невозможным . Любое решение, связанное с наследованием , кажется неприменимым, так как события INotifyPropertyChanged охватывают все элементы, их необходимо вызывать для всех (включая базовый класс) элементов во время назначения. Я также думал о написании собственного сериализатора для класса, который игнорировал бы элемент события или вводил пользовательские атрибуты, позволяющие скрывать элементы, но для меня это наихудший вариант. Я хотел бы продолжать использовать функции маршаллинга по умолчанию, если это вообще возможно.

Есть ли способ достичь этого?

Стоит отметить, что у меня нет доступа и контроля над C ++ пишет и читает эти структуры, и я не вижу причины для этого. Наличие объекта события в любой форме в файле не имеет смысла. Также я использую. NET Framework 4.7.2 с Visual Studio 2017.

...