Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2015.09.10;
Скачать: CL | DM;

Вниз

Общий тип для манипуляции несовместимыми типами с общими свойств.   Найти похожие ветки 

 
Дмитрий   (2014-03-05 17:40) [0]

Хочу сделать универсальный объект, который позволили бы единобразно обращаться к некоторым общим свойствам гридов разных типов.
В частности в проекте встречаются  одновременно DBGrid, RxDBGrid, DBGridEh.
Для реализации нужной функциональности сетки нужно обращаться к свойствам DataSource, OnFilter... и т.д., которые имеются у всех этих типов.
Возможно ли сделать объект или приведение типа, чтобы можно было привязывать любой тип сетки
вроде UniGrid.DataSource:=...


 
clickmaker ©   (2014-03-05 17:41) [1]

как вариант, RTTI либо класс-адаптер


 
Дмитрий   (2014-03-05 18:11) [2]

Стоило пожаловаться, как что-то получилось.
Приводить тип к TDBGrid отказывался четырьмя лапами
Объявил урезаный тип и прямо в лоб преобразовал

type
 TSomeGrid = class
 DataSource : TDataSource;
 OnKeyPress: TKeyPressEvent;
end;
...
result:=TSomeGrid(self.Grid).DataSource;
...


 
Inovet ©   (2014-03-05 19:08) [3]

> [2] Дмитрий   (05.03.14 18:11)
> Приводить тип к TDBGrid отказывался четырьмя лапами

Ну. А к TCustomDBGrid как?


 
Дмитрий   (2014-03-05 20:03) [4]

var
 dbgc: TCustomDBGrid;
 dbgeh: TDBGridEh;
begin
 dbgc:= dbgeh as TCustomDBGrid;

F9
Incompatible types: "TCustomDBGrid" and "TDBGridEh"

а если
 dbgc:= TCustomDBGrid(dbgeh) ;
то переваривает

Сейчас думаю, как мне передать грид в качестве параметра
Если опысываю метод как
TExtend.Create(Grid :TSomeGrid)
...
begin
TExtend.Create(DBGridEh1);
end;
то вызывает ошибку


 
Юрий Зотов ©   (2014-03-06 00:10) [5]

Если
Incompatible types: "TCustomDBGrid" and "TDBGridEh"
то
dbgc:= TCustomDBGrid(dbgeh) ;
делать нельзя.

Ищите общего предка для всх гридов - его и используйте.


 
Inovet ©   (2014-03-06 00:32) [6]

> [4] Дмитрий   (05.03.14 20:03)
> Incompatible types: "TCustomDBGrid" and "TDBGridEh"

Так, что-то автор EhLib говорил, что забил на DBGrid и сделал всё по-своему. Надо смотреть в описании.


 
Inovet ©   (2014-03-06 00:37) [7]

> [0] Дмитрий   (05.03.14 17:40)
> OnFilter

А это где в TDBGrid? Уверен что делаешь то, что хочешь получить?


 
Юрий Зотов ©   (2014-03-06 00:58) [8]

Сдается мне, что общий предок есть, но к DB не имеет никакого отношения. Значит, остается RTTI.


 
Дмитрий   (2014-03-06 02:36) [9]

После применения
dbgc:= TCustomDBGrid(dbgeh) ;
возникли разные интересные эффекты

Юрий, подскажите, как добиться нужного эффекта через RTTI?


 
Дмитрий   (2014-03-06 02:38) [10]

Общий предок TDBGrid и TDBGridEh где-то в районе TComponent;


 
Inovet ©   (2014-03-06 07:12) [11]

> [10] Дмитрий   (06.03.14 02:38)
> Общий предок TDBGrid и TDBGridEh где-то в районе TComponent;

TCustomGrid. Естественно никакого DataSource в нём нет.

Ты вот лучше скажи - для чего в одном проекте куча разных гридов? Зачем к разным прикручивать одинаковую функциональность? Если ответ - так получилось, теперь лень переделывать. То не лениться и переделать на один. Если действительно необходимо, ну тогда, как выше сказано - через RTTI проверять тип объекта и в зависимости от типа вызывать нужный метод.


 
Юрий Зотов ©   (2014-03-06 09:05) [12]

> Дмитрий   (06.03.14 02:36) [9]

> После применения
> dbgc:= TCustomDBGrid(dbgeh) ;
> возникли разные интересные эффекты


Разумеется. Это же неконтролируемое приведение к классу, который на самом деле предком не является. Тут возможны любые чудеса. И еще хорошо, если выскочит исключение - а ведь оно может и не выскочить, просто будет хорошо запрятанный глюк.

> как добиться нужного эффекта через RTTI?

См. исходники модуля TypInfo. Там куча полезных функций, которые позволяют работать со свойствами через их имена.

Но и это может не помочь. Например, если в двух классах одно и то же по сути свойство имеет разные имена, то Ваша задумка не прокатит. Поэтому присоединяюсь к [11].


 
Дмитрий   (2014-03-06 15:19) [13]

Разные гриды в проекте сложились исторически, на протяжении нескольких лет.
Нужна возможность легко и быстро прикрутить одинаковые фильтры и сортировки и отрисовки.
Для каждой сетки отдельно это утомительно.

Перед тем как по-простому, в лоб, приводить типы, делал так

 if (self.Grid is TDBGridEh) then  
result:=(self.Grid as TDBGridEh).DataSource;
 if (self.Grid is TDBGrid) then  
result:=(self.Grid as TDBGrid).DataSource;
 if (self.Grid is TRxDBGrid) then    
result:=(self.Grid as TRxDBGrid).DataSource;

Была надежда на возможность сократить.


 
Дмитрий   (2014-03-06 15:28) [14]

и так

 if (Grid.ClassName="TDBGrid")
   or (Grid.ClassName="TDBGridEh")
   or (Grid.ClassName="TRxDBGrid")
 then  begin
   self.Grid:=TSomeGrid(Grid);
   Create(self.DataSource.DataSet); //DataSource - проперть
//    self.Grid.OnKeyPress:= KeyPress;


 
Inovet ©   (2014-03-06 15:43) [15]

> [13] Дмитрий   (06.03.14 15:19)

> [14] Дмитрий   (06.03.14 15:28)

Первое и оставь


 
Дмитрий   (2014-03-06 17:38) [16]

Хотелось бы что-то вроде
SetProp(Object, "DataSource", DataSource);
SetProp(Object, "OnKeyPress", KeyPress);
или
Object.Prop("DataSource"):= DataSource;
Object.Prop(""OnKeyPress"):= KeyPress;
Чтобы в результате были заполнены поля переданного объекта в не зависимости TDBGridEh это или TRxDBGridEh


 
Дмитрий   (2014-03-06 20:44) [17]

С обработчиком получилось, вот таким методом

procedure SetObjectMetod(DestinObj : TObject; RemoveMetod: string; SourceObj : TObject; AlterMetod : string);
var
 PropInfo: PPropInfo;
 CommonMethod: TMethod;
begin
   PropInfo := GetPropInfo( DestinObj.ClassInfo, RemoveMetod);
   if PropInfo <> nil then
   begin
     CommonMethod.Data := SourceObj;
     CommonMethod.Code := SourceObj.MethodAddress(AlterMetod);
     SetMethodProp( DestinObj, PropInfo, CommonMethod );
   end;
end;
...
//вызов
 SetObjectMetod(Grid, "OnKeyPress", Self, "KeyPress");
...


 
Дмитрий   (2014-03-20 16:49) [18]

Пытаюсь добраться до поля SelectedField грида Grid - поле типа TObject, где хранится ссылка на объект типа TDBGridEh (передаю в тестовом примере).

function TFindExt.GetSelectedField : TField;
var
 obj : TObject;
begin
 result:=nil;
//1- не срабатывает, выдает сообщение "свойство не найдено" и выходит из процедуры}
 obj :=GetObjectProp(Grid,  "SelectedField"); //
 if (obj is TField) then
   result:=TField(obj);

//2-работает, возвращает ожидаемое значение
 if (self.Grid is TDBGridEh) then
   result:=TDBGridEh(self.Grid).SelectedField;
end;

Почему не срабатывает GetObjectProp?


 
icWasya ©   (2014-03-20 17:13) [19]

через GetObjectProp можно достать только published-property


 
Дмитрий   (2014-03-20 17:20) [20]

Как тогда быть?
Попробовал через FindComponent

//  obj := (self.grid as TComponent).FindComponent("SelectedField");
 obj := self.grid.FindComponent("SelectedField");
 if (obj is TField) then
   result:=TField(obj);

Тоже не сработало.


 
Германн ©   (2014-03-20 17:51) [21]


> Попробовал через FindComponent
> Тоже не сработало.

Не расстраивайся. В Дельфи еще много функций начинающихся словом Find. Авось какая-нибудь из них сработает. Продолжай пробовать.


 
Дмитрий   (2014-03-20 19:58) [22]

Подозреваю ехидство.
Вы можете подсказать поконкретнее?


 
clickmaker ©   (2014-03-20 21:50) [23]

> [22] Дмитрий   (20.03.14 19:58)

grid.FindComponent ищет среди компонентов, владельцем которых является grid.
SelectedField - это по сути вычисляемое свойство, которое указывает на одно из полей источника данных в контексте текущей записи.


 
Германн ©   (2014-03-21 02:08) [24]


> Дмитрий   (20.03.14 19:58) [22]
>
> Подозреваю ехидство.

Правильно подозреваешь.
Но это не совсем ехидство. На сём форуме многие авторы вопросов пытались добиться желаемого результата методом тыка. Но только одного я знаю, который добился.
Но даже он/она имел гораздо более высокий уровень базовых знаний, чтобы не пытаться использовать функции/процедуры, которые явно относятся к другой теме.


 
Дмитрий   (2014-03-21 16:09) [25]

Как мне обратиться к известным свойствам и полям объекта заранее неизвестного типа?


 
clickmaker ©   (2014-03-21 16:32) [26]

> [25] Дмитрий   (21.03.14 16:09)

тебе уже ответили. К published можно через RTTI
к не-published - как вариант - через свой класс-адаптер


 
Дмитрий   (2014-03-21 16:45) [27]

У меня в любом случае класс-адаптер, что с РТТИ, что без.
Как без прямого указания типа сделать класс-адаптер?

Вариант с прямым указанием и приведением типа
if (self.Grid is TDBGridEh) then  
result:=(self.Grid as TDBGridEh).DataSource;

не очень нравится тем, что для привязки еще одного типа, например Jedi-грида придется править все процедуры и функции.


 
clickmaker ©   (2014-03-21 16:53) [28]

что ж это за проект, где целая толпа гридов заюзана? )


 
Дмитрий   (2014-03-21 17:14) [29]

Проект обычный.
Где со временем пришлось добавлять функционал.
В частности, отображение мемо и "заморозку столбцов", которые вызвали переход на ЕхЛиб.
Кроме этого, хочу иметь "свободу выбора гридов" для других проектов.
Итоговый результат - создание типовой формы для просмотра таблиц или выбора значений из таблиц с сортировкой и фильтром при помощи пары строк кода.


 
clickmaker ©   (2014-03-21 17:24) [30]

> создание типовой формы для просмотра таблиц или выбора значений
> из таблиц

и в этой форме могут быть использованы все эти виды гридов?


 
Дмитрий   (2014-03-21 17:41) [31]

Странный вопрос.
Можно и левое ухо правой рукой чесать.
Но мы же не обязаны пользоваться этой возможностью.

Мне нужна прослойка между гридом и датасетом, реализующая отсутствующий функционал.
И возможность подложить эту прокладку под часто используемые гриды и датасеты.
И все это обернуть функцией создания и отображения типовой формы.

С датасетами проще есть общий тип.
С гридами проблема.


 
Германн ©   (2014-03-22 03:27) [32]

Дмитрий   (21.03.14 17:41) [31]

Странный вопрос.
Можно и левое ухо правой рукой чесать.
Но мы же не обязаны пользоваться этой возможностью.

Мы не обязаны. А кто тебя заставил?


 
clickmaker ©   (2014-03-23 22:04) [33]

> прослойка между гридом и датасетом

published-свойства типа DataSource, которые у всех гридов есть, можно через RTTI получить.
А под специфичные св-ва типа SelectedField все равно придется код напильником затачивать


 
KSergey ©   (2014-03-24 11:08) [34]

> Дмитрий   (06.03.14 15:19) [13]

По-моему отличный и довольно производительный вариант.
Написал один раз - и забыл, т.е. занялся чем-то более полезным, чем "наведение красоты". Которое завсегда совершенно бестолковое.


 
Дмитрий   (2014-03-24 17:57) [35]


> KSergey ©   (24.03.14 11:08) [34]
> По-моему отличный и довольно производительный вариант.

Вариант отличный, главное, рабочий.
И пока единственный.
Удручает один момент: для пристежки Джедайского Грида добавки делать во все процедуры.


 
clickmaker ©   (2014-03-24 18:02) [36]

> добавки делать во все процедуры

зачем во все? недостаточно одного статического метода-хелпера?


 
Дмитрий   (2014-03-24 19:47) [37]

Что будет делать это метод?


 
clickmaker ©   (2014-03-24 19:50) [38]

[13]


 
Дмитрий   (2014-03-25 17:01) [39]

Остальные требуемые поля и свойства этот же метод будет получать?
)


 
Inovet ©   (2014-03-25 17:06) [40]

> [39] Дмитрий   (25.03.14 17:01)

Тебе Датасет надо или остальные поля и свойства? Какие тогда остальные?


 
clickmaker ©   (2014-03-26 10:45) [41]

function TGridHelper.GetProp(AGrid: TComponent; const APropName: string): TObject;
begin
 if (APropName = "DataSource") then begin
   if (AGrid is TDBGridEh) then  
     result:=(AGrid as TDBGridEh).DataSource;
   else if (AGrid is TDBGrid) then  
    result:=(AGrid as TDBGrid).DataSource;
   if (AGrid is TRxDBGrid) then    
    result:=(AGrid as TRxDBGrid).DataSource;
 end else
 if (APropName = "SelectedField") then begin
   if (AGrid is TDBGridEh) then  
     result:=(AGrid as TDBGridEh).SelectedField;
   ...
 end else
 if...
end;


 
Дмитрий   (2014-03-26 17:20) [42]

В большей степени мне нужны поля и свойства грида.
Align, color, columns, datasource, Drawmemotext, EditActions, Enabled, EvenRowColor, FixedColor, Flat, FrozenCols, Height, Hint, Left, Name, OddRowColor, Options, ReadOnly, Tag, Visible, Width
Еще некоторые другие типа Owner-Parent и некоторые обработчики OnKeyPressed-OnDrawColumnCell

У датасетов облегчает ситуацию наличие общего совместимого типа, у гридов такого нет.

> clickmaker ©   (26.03.14 10:45) [41]
> function TGridHelper.GetProp(AGrid: TComponent; const APropName:
>  string): TObject;
> begin...

Мысль понятна-объединить в один метод.
Возможно, с точки зрения структуры и правок это будет удобно.


 
Inovet ©   (2014-03-26 17:27) [43]

> [42] Дмитрий   (26.03.14 17:20)

Какой в этом смысл, если они разные и наборы их разные? При том, что часть из перечисленного вообще-то не этими гридамиопределена и общая для всех, и доступна нормальными способами.


 
sniknik ©   (2014-03-26 18:07) [44]

> Возможно, с точки зрения структуры и правок это будет удобно.
гарантирую, это будет жутко неудобно и глючно.

сам представь, все что ты делаешь в 1 строку будешь делать в 50 ради абстрактной универсализации. да эти 50 строк, вместо одной у тебя будут "спрятаны" в объекте но зависимости в работе с ним, "внешние", останутся. и необходимость правки именно самого кода обеспечивающего "универсальность" тоже (по умолчанию, сделает кто-то новый грид и как же универсальность если его не поддержать?).


 
Дмитрий   (2014-03-26 18:29) [45]

Inovet ©   (26.03.14 17:27) [43]
Переписал из инспектора используемые свойства ЕхГрида.
Некоторые свойства, вроде SelectedField так не помню, всплывают в процессе переделки прежнего модуля.

sniknik ©   (26.03.14 18:07) [44]
Принципиального улучшения [41] не несет по сравнению с [13], кроме группировки в одном блоке.
Во многих случаях потребуется еще одно приведение типов.
Дополнительная операция может быть заметна в обаботчиках типа OnCalc или OnDrawCell


 
sniknik ©   (2014-03-27 11:50) [46]

> Принципиального улучшения
я не про разницу кода 13 vs 41, а в принципе "за идею"... любая "универсализация" чего-то настолько различного приведет к проблемам.

как пример могу привести уже набивший оскомину ADOTable, ADOQuery "универсализировавший" логику работы с ними "под BDE".
где уже этот BDE, а проблемы из-за подобного решения до сих пор есть.


 
Дмитрий   (2014-04-14 18:53) [47]

К слову, мне не обязательно требуется реализация здесь и сейчас всех свойств ДжедайГрида и прочих.
Скорее, мне нужна болванка, которая сейчас позволяет крутить ГридЕх, в которую при потребности легко добавить прочие типы.


 
Юрий Зотов ©   (2014-04-14 22:51) [48]

> Дмитрий   (14.04.14 18:53) [47]

Прошло больше месяца, а решения так и нет. Не значит ли это, что его действительно просто нет?


 
Германн ©   (2014-04-15 02:27) [49]


> Дмитрий   (14.04.14 18:53) [47]
>
> К слову, мне не обязательно требуется реализация здесь и
> сейчас всех свойств ДжедайГрида и прочих.
> Скорее, мне нужна болванка, которая сейчас позволяет крутить
> ГридЕх, в которую при потребности легко добавить прочие
> типы.

А к своему тёзке, автору EhLib не обращался?


 
Дмитрий   (2014-04-15 17:22) [50]


> Германн ©   (15.04.14 02:27) [49]
> А к своему тёзке, автору EhLib не обращался?

Нет.
То, что нужно было от ЕхГрида обходился поиском по форумам.
А спросить про универсальный коннектор не достает наглости.
Кроме меня никому не нужно.


> Юрий Зотов ©   (14.04.14 22:51) [48]
> решения так и нет. Не значит ли это, что его действительно
> просто нет?

Так-то решение есть - прописать каждое свойство ручками.
Чем потихоньку и занимаюсь, в фоновом режиме.
Отсутствует желаемое решение.
С мороженками и печеньками.
)


 
Юрий Зотов ©   (2014-04-16 12:13) [51]

> Отсутствует желаемое решение.

Его я и имел в виду. И в полноценном виде его действительно не существует (о чем здесь уже говорилось) - слишком разные компоненты.



Страницы: 1 2 вся ветка

Текущий архив: 2015.09.10;
Скачать: CL | DM;

Наверх




Память: 0.61 MB
Время: 0.068 c
3-1304681525
wwowa
2011-05-06 15:32
2015.09.10
Перенос данных


15-1419283803
Юрий
2014-12-23 00:30
2015.09.10
С днем рождения ! 23 декабря 2014 вторник


15-1418419802
Юрий
2014-12-13 00:30
2015.09.10
С днем рождения ! 13 декабря 2014 суббота


15-1420134946
ProgRAMmer Dimonych
2015-01-01 20:55
2015.09.10
Где взять MSDN Library за август 2006?


15-1418679002
Юрий
2014-12-16 00:30
2015.09.10
С днем рождения ! 16 декабря 2014 вторник