Здравствуйте!
Перевожу два проекта (один старый, другой начал делать) в BLToolkit. Часто встречаю разные непонятки. Кое-как выруливаю, но сейчас вообще темень.
Контекст проблемы (пример упрощённый):
public abstract class PhoneNumber : PhoneNumberBase, IContact
{
/// <summary>
/// Является ли данный телефон основным для связи
/// </summary>public abstract bool IsPrimary { get; set; }
#region ● IContact implementation ●
public abstract Guid ContactTypeID { get; set; }
//
//...
//public/*abstract*/stringContactComments{ get; set; }
{
get
{
return FromFunc(Comments);
}
set
{
Comments = ToFunc(value);
}
}
#endregion • IContact implementation •
[MaxLength(192)]
public abstract string Comments {get;set;}
}
Собственно вопрос: как сохранить Editable-ность у ContactComments?
Куда копать?
Ещё одно изменение — атрибуты [SetValue, GetValue]. Они говорят генератору, что данное свойство следует использовать для реализации свойств в родительском объекте (см. самый первый пример).
Здравствуйте, IT, Вы писали:
IT>Что значит сохранить Editable-ность?
Спасибо, что ответили!
Имеется ввиду, чтобы IsDirty срабатывал как надо. Ведь если свойство не абстрактное, то и все прелести EditableObject не будут работать? или что-то не то?
Здравствуйте, smallit, Вы писали:
S>Имеется ввиду, чтобы IsDirty срабатывал как надо. Ведь если свойство не абстрактное, то и все прелести EditableObject не будут работать? или что-то не то?
Здравствуйте, smallit, Вы писали:
S>Имеется ввиду, чтобы IsDirty срабатывал как надо. Ведь если свойство не абстрактное, то и все прелести EditableObject не будут работать? или что-то не то?
По идее Comments будет Editable. Этого не достаточно?
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, IT, Вы писали: IT>Почему нет? Какую задачу вы решаете?
Даже, если выкинуть сеттер, то останется — геттер ==> свойство уже не абстрактное.
геттер должен возвращать некоторое преобразуемое значение, а не 1 в 1. Чисто теоретически: а можно вообще как-нить вклиниваться в перекачку данных туда-сюда? (про АОП я видел, но думаю, что при активной работе, всё-таки будут тормоза, делегаты в .NET — медленная вещь)
Игорь, огромное спасибо за ответы и за сам BLToolkit !
PS. И всё-таки, есть ли решение вот этого: S>Тогда вопрос по вот этому топику. Там Павел предложил изменить EditableValue. Но чего-то я не понял как именно. Может подскажете?
Здравствуйте, smallit, Вы писали:
S>PS. И всё-таки, есть ли решение вот этого: S>>Тогда вопрос по вот этому топику. Там Павел предложил изменить EditableValue. Но чего-то я не понял как именно. Может подскажете?
Здравствуйте, smallit, Вы писали:
IT>>Почему нет? Какую задачу вы решаете? S>Даже, если выкинуть сеттер, то останется — геттер ==> свойство уже не абстрактное. S>геттер должен возвращать некоторое преобразуемое значение, а не 1 в 1. Чисто теоретически: а можно вообще как-нить вклиниваться в перекачку данных туда-сюда?
Я к тому, что в приведённом выше примере ContactComments работает через Comments, который editable, а следовательно изменение ContactComments будет приводить к изменению Comments и соответственно делать весь объект IsDirty. Я пытаюсь понять зачем нужен IsDirty дополнительно на ContactComments.
S>Игорь, огромное спасибо за ответы и за сам BLToolkit !
Да фигня вопрос. Я ещё, кстати, крестиком умею.
S>PS. И всё-таки, есть ли решение вот этого: S>>Тогда вопрос по вот этому топику. Там Павел предложил изменить EditableValue. Но чего-то я не понял как именно. Может подскажете?
Решение есть всегда, вопрос только в его адекватности. Сам по себе EditableObject имеет отностительно непростую реализацию. Там генерируется куча всего. Здесь небольшое объяснение. Только вместо пар _originalXXX / _currentXXX значений используется один объект — EditableValue. Генератором всё это увязывается в один генерируемый класс. Для увязывания используются атрибуты, навешанные на EditableObject и интерфейсы. Например, [GlobalInstanceType(typeof(byte),typeof(EditableValue<byte>))] говорит генератору, что для любого свойства типа byte для его внутренней имплементации следует использовать тип EditableValue<byte>. Этот тип реализует ряд интерфейсов, которые позволяют связывать его с EditableObject при генерации.
Если вы реализуете свой объект по аналогии с EditableValue, то можно получить, то, что вам нужно. Но это всё как бы не мало кода.
Кстати, привязать внутреннюю реализацию к отдельному свойству можно применением атрибута InstanceType (не Global) конкретно к этому полю.
Если нам не помогут, то мы тоже никого не пощадим.
IT>>>Почему нет? Какую задачу вы решаете? S>>Даже, если выкинуть сеттер, то останется — геттер ==> свойство уже не абстрактное. S>>геттер должен возвращать некоторое преобразуемое значение, а не 1 в 1. Чисто теоретически: а можно вообще как-нить вклиниваться в перекачку данных туда-сюда?
IT>Я к тому, что в приведённом выше примере ContactComments работает через Comments, который editable, а следовательно изменение ContactComments будет приводить к изменению Comments и соответственно делать весь объект IsDirty. Я пытаюсь понять зачем нужен IsDirty дополнительно на ContactComments.
Здравствуйте, IT, Вы писали:
IT>Я к тому, что в приведённом выше примере ContactComments работает через Comments, который editable, а следовательно изменение ContactComments будет приводить к изменению Comments и соответственно делать весь объект IsDirty. Я пытаюсь понять зачем нужен IsDirty дополнительно на ContactComments.
Это простой пример. Там таких очень много. Нам нужно (по идее) одно универсальное решение. Уж слишком там всё разное сейчас. А ещё будет...
IT>Да фигня вопрос. Я ещё, кстати, крестиком умею.
Я тоже. Но написать такой же BLToolkit почему-то не помогло
IT>Решение есть всегда, вопрос только в его адекватности. Сам по себе EditableObject имеет отностительно непростую реализацию. Там генерируется куча всего. Здесь небольшое объяснение. Только вместо пар _originalXXX / _currentXXX значений используется один объект — EditableValue. Генератором всё это увязывается в один генерируемый класс. Для увязывания используются атрибуты, навешанные на EditableObject и интерфейсы. Например, [GlobalInstanceType(typeof(byte),typeof(EditableValue<byte>))] говорит генератору, что для любого свойства типа byte для его внутренней имплементации следует использовать тип EditableValue<byte>. Этот тип реализует ряд интерфейсов, которые позволяют связывать его с EditableObject при генерации.
Ага. с этим уже понятно стало — просмотр исходников в этом очень помог.
IT>Если вы реализуете свой объект по аналогии с EditableValue, то можно получить, то, что вам нужно. Но это всё как бы не мало кода.
Вот тут и загвоздка...
IT>Кстати, привязать внутреннюю реализацию к отдельному свойству можно применением атрибута InstanceType (не Global) конкретно к этому полю.
Да — это уже тоже поняли.
Кстати, BorisKV предложил занести EditableObjectAdvanced<> в BLToolkit. Мы тоже голосуем за это!
Но есть один воросик. <T> — это только для того чтобы нести вверх по иерархии CreateInstance, Clone, Copy? Т.е. если они не нужны, то и класс можно отсавить без дженерик-а?
Здравствуйте, SmallInt, Вы писали:
SI>Вот единственное, чего не понятно. Как повлияет на скорость такое изменение? Рефлексия вроде не используется, или ... ?
Мда. Прочитав до конца топик, стало понятно, что и кроме рефлексии, там всё не так просто.
SI>Кстати, BorisKV предложил занести EditableObjectAdvanced<> в BLToolkit. Мы тоже голосуем за это!
Да вот в общем это... — я с Игорем давно уже это обсуждал, просто как-то руки не дошли. Да и надо было бы пополировать слегка для библиотечного решения (пооптимизировать и т.д). Время, время, время...
SI>Но есть один воросик. <T> — это только для того чтобы нести вверх по иерархии CreateInstance, Clone, Copy? Т.е. если они не нужны, то и класс можно отсавить без дженерик-а?
В общем да.
и проперти будет репортится как измененная.
SI>Вот единственное, чего не понятно. Как повлияет на скорость такое изменение? Рефлексия вроде не используется, или ... ?
Естественно, это решение будет слегка медленнее чем без этой ручной возни, так тут есть циклы, запросы списков, и т.д, но не за счет более медленного доступа к полю. Суть этого решения в том, что как раз работает тотже код, что и был бы сгенерен BLT. Понятно что за фишки и удобства надо платить, мне кажется, что в данном случае плата разумна. Когда буду засовывать это решение в BLT я еще поиграюсь с профайлером и может чуток еще что-нибуть выжму.
Если вы посмотрите к примеру то что генерит BLT для IsDirtyMember то увидете нечто подобное (пишу по памяти — могут быть огрехи) на:
SI>Мда. Прочитав до конца топик, стало понятно, что и кроме рефлексии, там всё не так просто.
Такие дебри в которых обитает BLT почти всегда не просты и прозрачны. В целом обычно почти всегда — шаг влево/вправо от политики партии (неважно где — в .NET Framework, BLT или любой другой библиотеке) и начинается геморой.
топика. Почему AndrewVK и MozgC так противятся тому, что ref-параметр и возврат очень плохо? Мы же не на флэшке данные переносим между методами? Или чего-то мы конкретно не понимаем в этой теме?
топика. Почему AndrewVK и MozgC так противятся тому, что ref-параметр и возврат очень плохо? Мы же не на флэшке данные переносим между методами? Или чего-то мы конкретно не понимаем в этой теме?
Ну это лучше всего спросить у самого AndrewVK и MozgC почему конкретно они противятся ref.
Я понимаю почему Игорь так сделал в те далекие времена. Насчет возврата nullable типов — их тогда не было, к тому же это таже структура. Насчет структур...
Да, можно сделать было нечто вида
public IsDirtyReturnValue IsDirtyMember(PropertyInfo propertyInfo, string memberName)
{
if (memberName != propertyInfo.Name)
return new IsDirtyReturnValue {processed=false};
return new IsDirtyReturnValue {processed=true,isDirty=IsDirty};
}
и меняем EditableObject
public virtual bool IsDirtyMember(string memberName)
{
bool isDirty = false;
if (this is IMemberwiseEditable)
{
IsDirtyReturnValue returnValue = ((IMemberwiseEditable)this).IsDirtyMember(null, memberName);
if (returnValue.processed)
isDirty = returnValue.processed;
}
return isDirty;
}
Я думаю общий принцип понятен. А теперь предпологаем что в объекте 150-200 полей и встает вопрос — сколько операций создания (я понимаю что это на стеке...), копирования и т.д. мы получим. Может я конечно преувеличиваю (бенчмарков я не делал), и все не так страшно, но мне почему-то кажется, что решение Игоря хотя и менее "кошерное" с точки зрения преверженцев красоты архитектуры и чистоты решений, но все же более быстрое и разумное, хотя наверняка будут возражения.
А вообще такую тему лучше обсуждать где-нибудь в философии или священных войнах...
... << RSDN@Home 1.2.0 alpha 4 rev. 1238>>
Re: GetValue, SetValue и EditableObject
От:
Аноним
Дата:
30.08.11 07:25
Оценка:
Здравствуйте, Аноним, Вы писали:
Вообщем, возвращаясь с первому сообщению топика. Хочу выразить более кратко и ясно суть проблемы:
Как сохранить Editable-ность объктов, реализующих произвольные интерфейсы. Реализация-то может быть не совсем такая уж очевидная. Выход только один: EditableObject — это только "аля DTO", всё остальное — создавать/писать отдельно.