2016-05-11 8 views
1

У меня есть общий класс с одним аргументом, который представляет собой элемент третьей стороны DLL для сериализации объектов типа T. То, что я хотел бы сделать, это добавить «грязную» карту в мой класс и лениво вызвать ее, когда изменяется один из моих вложенных свойств элемента.C# по отслеживанию изменения вложенных свойств

Возможно ли, когда доступ к собственности будет улавливать запрос и определить, какое свойство меняется? Что, если выполняется SET, я могу зарегистрировать, что под-свойство P теперь загрязнено и его необходимо сохранить? Или, по крайней мере, один бит, который указывает, что SOMETHING изменился?

public class ResourceSerializer<T> 
    where T : Base, new() 
    { 
    T element; 
    Dictionary<String,Boolean> dirtyMap; 

    public T Element { get { return this.getElement(); } } 
    public Boolean IsDirty { get; private set; } 

    public ResourceSerializer() 
    { 
    dirtyMap = new Dictionary<string,bool>(); 
    element = new T(); 
    // code to reflect back upon T's Properties and build out the dirtyMap. 
    // I already can do this I just omitted it. 
    // in my Person example there would be keys: 'FirstName', 'LastName', 'Age', 'Gender', 'PrimaryAddress' 
    } 


    // how can I call this programmatically? 
    void flagDirty(String property) 
    { 
    dirtyMap[property] = true; 
    this.IsDirty = true; 
    } 
    T getElement() 
    { 
    // In case I need to do a thing before returning the element. 
    // Not relevant to the question at hand. 
    return this.element; 
    } 
} 

несколько продвинутый пример «базы». Вы можете видеть, как мне нужно выполнять мои действия, поскольку не все является примитивным. У меня есть класс уровня менеджера, который регистрирует все эти объекты ResourceSerializer.

public class Base 
{ 
    public Base() 
    { 

    } 
} 
public enum gender 
{ 
    Male, 
    Female, 
    Other, 
    Unspecified, 
} 
    public class Address : Base 
{ 
    public String Street { get; set; } 
    public String State { get; set; } 
    public String Zip { get; set; } 
    public Address() : base() 
    { 

    } 
} 
public class Person : Base 
{ 
    public String FirstName { get; set; } 
    public String LastName { get; set; } 
    public Int16 Age { get; set; } 
    public gender Gender { get; set; } 
    public Address PrimaryAddress { get; set; } 
    public Person() : base() 
    { 

    } 
} 
public class Patient : Person 
{ 
    public Person PrimaryContact { get; set; } 
    public Patient() : base() 
    { 

    } 
} 

и небольшой класс я превратился бы в методе испытания позже ..

public class DoThing 
    { 
    public DoThing() 
    { 
     ResourceSerializer<Person> person = new ResourceSerializer<Person>(); 
     person.Element.Age = 13; // catch this and mark 'Age' as dirty. 
    } 
    } 

ответ

0

Без пользовательского сеттера нет, нет ничего, чтобы сделать это.

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

Если вы ленитесь, как я, я бы создал анализатор, который в начале моего приложения сканирует все мои классы, отмеченные атрибутом, и со всеми свойствами, созданными как виртуальные, а затем с использованием кодированного кода я бы создал новый класс, который наследуется от найденного класса и реализует INotifyPropertyChanged, тогда вы можете иметь общий Factory, который возвращает экземпляры этих новых классов, когда тип общего вызова имеет известный зарегистрированный тип.

Я использовал это раньше для классов, в которых я хотел иметь удаленные свойства, просто пометил класс, а моя система сканирования переписала геттер/сеттер для прозрачного выполнения удаленных вызовов, концепция в конце - то же самое.

Это очень много работы в начале, но если у вас есть тонна классов, это будет намного меньше кода для написания, чем реализация INotifyPropertyChanged на всех ваших классах.

+0

Да, ссылка dll У меня есть сотни классов, и ни одна из их свойств не является virual. Я надеялся отразить все это. – user3562367

+0

Тогда лучше всего создать такую ​​систему, как я описал, воссоздать типы классов динамически с помощью кодовода. – Gusman

+0

Whops, не читал о виртуальном бите ... если это ваш случай, то, возможно, используя ключевое слово 'new', вы можете это сделать, просто не забудьте прочитать и написать базовое свойство. – Gusman