Имя: Пароль:
1C
1С v8
Определить вид объекта по ссылке
,
0 thomY100
 
14.09.12
10:55
Добрый день, возник такой вопрос, как определить, что за объект метаданных используется, по его ссылке, т.е
есть тип СправочникСсылка.Сотрудники, например, нужно определить, что это именно справочник, если ДокументСсылка, то что это документ соответственно, как это сделать?
1 ptiz
 
14.09.12
10:58
Если Справочники.ТипВсеСсылки.СодержитТип(ТипЗнч(Ссылка)) Тогда
...это справочник
2 thomY100
 
14.09.12
11:00
ок, спасибо
3 GANR
 
14.09.12
11:09
Ещё вариант...

ТипСтрокой = Строка(ТипЗнч(Ссылка));
ВидМетаданногоСтрокой = Лев(ТипСтрокой, Найти(ТипСтрокой, ".") - 1);

Если ВидМетаданногоСтрокой = "ДокументСсылка" Тогда
ИначеЕсли ВидМетаданногоСтрокой = "СправочникСсылка" Тогда
...
ИначеЕсли ВидМетаданногоСтрокой = "ЗадачаСсылка" Тогда
КонецЕсли;

Возможно, это будет несколько побыстрее, чем (1) работать.
4 ptiz
 
14.09.12
11:13
Тогда уж
Метаданные.Справочники.Содержит(Ссылка.Метаданные())
5 GANR
 
14.09.12
12:07
(4) А всё-же как быстрее по замеру производительности - (1), (3) или (4) ???
6 Sammo
 
14.09.12
12:17
(5) 3 критично к языку, например
7 Reset
 
14.09.12
12:18
(3) Не рабочий, т.к. Строка(ТипЗнч(Ссылка)) не будет содержать ни "ДокументСсылка", ни "СправочникСсылка"
[верно для 8.2]
8 Reset
 
14.09.12
12:20
Если через строки то уж тогда Ссылка.Метаданные().ПолноеИмя()
9 Maxus43
 
14.09.12
12:20
(5) на 8.2 не будет работать (3), там Синоним объекта в строке
10 Reset
 
14.09.12
12:20
я бы (4) использовал
11 Maxus43
 
14.09.12
12:21
по феншую имхо (1)
12 Reset
 
14.09.12
12:23
(11) только со скобками после ТипВсессылки :)
13 Reset
 
14.09.12
12:24
Согласен, исключает ошибку в случае если проверяемое значение не ссылочного типа
14 Maxus43
 
14.09.12
12:24
(13) и помоему быстрее чем через метаданные
15 Reset
 
14.09.12
12:31
(14) Затестил.
Справочники.ТипВсеСсылки().СодержитТип(ТипЗнч(Справочники.Валюты.ПустаяСсылка()))
примерно в два раза быстрее чем
Метаданные.Справочники.Содержит(Справочники.Валюты.ПустаяСсылка().Метаданные())

но в 2 раза вылилось что типа "5 миллинных секунды vs 9 миллионных"
16 Aleksey
 
14.09.12
12:33
Функция ПолучитьИмяБазовогоТипаПоТипуОбъекта(ТипОбъекта) Экспорт
   
   МетаданныеТипа = Метаданные.НайтиПоТипу(ТипОбъекта);
   
   Если МетаданныеТипа = Неопределено Тогда
       
       Возврат "УдалениеОбъекта";
       
   ИначеЕсли Метаданные.РегистрыСведений.Содержит(МетаданныеТипа) Тогда
       
       Возврат "РегистрыСведений";
       
   ИначеЕсли Метаданные.Документы.Содержит(МетаданныеТипа) Тогда
       
       Возврат "Документы";
       
   ИначеЕсли Метаданные.Справочники.Содержит(МетаданныеТипа) Тогда
       
       Возврат "Справочники";    
       
   ИначеЕсли Метаданные.РегистрыНакопления.Содержит(МетаданныеТипа) Тогда
   
       Возврат "РегистрыНакопления";    
       
   ИначеЕсли Метаданные.РегистрыБухгалтерии.Содержит(МетаданныеТипа) Тогда
   
       Возврат "РегистрыБухгалтерии";    
     
   Иначе
     
       Возврат "";
       
   КонецЕсли;
           
КонецФункции


Соответственно вызов

ИмяБазовогоТипа = ПолучитьИмяБазовогоТипаПоТипуОбъекта(ТипЗнч(ТекущийРеквизит.ПолучитьОбъект()));
17 GANR
 
14.09.12
12:37
(7)Тьху-ё и правда (((.

(14), (15) А вот как надо (Ссылка.Метаданные() - быстрейший способ получения метаданных):

ПолноеИмяМетаданного = Ссылка.Метаданные().ПолноеИмя();
ВидМетаданногоСтрокой = Лев(ПолноеИмяМетаданного, Найти(ПолноеИмяМетаданного, ".") - 1);

Если ВидМетаданногоСтрокой = "Документ" Тогда
//это документ
ИначеЕсли ВидМетаданногоСтрокой = "Справочник" Тогда
//это справочник
...
ИначеЕсли ВидМетаданногоСтрокой = "Задача" Тогда
//это задача
КонецЕсли;
18 GANR
 
14.09.12
12:39
(16) Очень медлительный вариант
19 Maxus43
 
14.09.12
12:41
короче (1) наше всё, остальное быдлокод! С пятницей!
20 Aleksey
 
14.09.12
12:43
(18) Зато правильный ибо не зависит от представления. А в практике уже были случае когда 1С меняла представление при смене платфйормы
21 GANR
 
14.09.12
12:45
(20) Это (17) тоже не зависит от представления. Насчет (3) - полностью согласен, я ошибся.
22 Reset
 
14.09.12
12:45
(17) Затестил.
ПолноеИмяМетаданного=Справочники.Валюты.ПустаяСсылка().Метаданные().ПолноеИмя();х=Лев(ПолноеИмяМетаданного, Найти(ПолноеИмяМетаданного, ".")-1)="Справочник";
Самый медленный вариант. Правда, с минимальным отставанием от других.
23 Reset
 
14.09.12
12:46
Тоже за (1) тогда ;)
24 GANR
 
14.09.12
12:48
(22) На операцию Справочники.Валюты.ПустаяСсылка() львиная доля времени уходит, а в (17) просто Ссылка.Метаданные() и всё.
25 Reset
 
14.09.12
12:49
(24) В идентичных условиях. См (15)
26 Reset
 
14.09.12
12:50
Возможно, (17) в случае именно "копмлексной функции" и минимально лучше будет по скорости, но (1) лучше по читабельности и надежности
27 Reset
 
14.09.12
12:50
Присоединяюсь, всех с пятницей.
28 GANR
 
14.09.12
13:28
(26) Выбрал ссылку на перечисление, чтоб внизу разветвляющейся структуры обоих алгоритмов было и проверок было максимум. (3) в 4 раза быстрее (1) уже при малом объеме метаданных (конфа в 5-7 раз меньше Бух 2.0)

Тестируем (3) на типе объекта "Перечисление"

&НаСервереБезКонтекста
Процедура Третий(СсылкаНаОбъект)
   
   ПолноеИмяМетаданного = СсылкаНаОбъект.Метаданные().ПолноеИмя();
   ВидМетаданногоСтрокой = Лев(ПолноеИмяМетаданного, Найти(ПолноеИмяМетаданного, ".") - 1);
   
   Если ВидМетаданногоСтрокой = "Документ" Тогда
       
   ИначеЕсли ВидМетаданногоСтрокой = "Справочник" Тогда
   
   ИначеЕсли ВидМетаданногоСтрокой = "ПланВидовХарактеристик" Тогда
       
   ИначеЕсли ВидМетаданногоСтрокой = "ПланВидовРасчета" Тогда
       
   ИначеЕсли ВидМетаданногоСтрокой = "Задача" Тогда
       
   ИначеЕсли ВидМетаданногоСтрокой = "БизнесПроцесс" Тогда
       
   ИначеЕсли ВидМетаданногоСтрокой = "Перечисление" Тогда
       
   КонецЕсли;
   
КонецПроцедуры


Время 0,00011

Тестируем (1) на типе объекта "Перечисление"

&НаСервереБезКонтекста
Процедура Первый(СсылкаНаОбъект)
   
   Если Документы.ТипВсеСсылки().СодержитТип(ТипЗнч(СсылкаНаОбъект)) Тогда    
       
   ИначеЕсли Справочники.ТипВсеСсылки().СодержитТип(ТипЗнч(СсылкаНаОбъект)) Тогда    
       
   ИначеЕсли ПланыВидовХарактеристик.ТипВсеСсылки().СодержитТип(ТипЗнч(СсылкаНаОбъект)) Тогда    
       
   ИначеЕсли ПланыВидовРасчета.ТипВсеСсылки().СодержитТип(ТипЗнч(СсылкаНаОбъект)) Тогда    
       
   ИначеЕсли Задачи.ТипВсеСсылки().СодержитТип(ТипЗнч(СсылкаНаОбъект)) Тогда    
       
   ИначеЕсли БизнесПроцессы.ТипВсеСсылки().СодержитТип(ТипЗнч(СсылкаНаОбъект)) Тогда    
       
   ИначеЕсли Перечисления.ТипВсеСсылки().СодержитТип(ТипЗнч(СсылкаНаОбъект)) Тогда    
       
   КонецЕсли;

КонецПроцедуры

Время 0,00046
29 Maxus43
 
14.09.12
13:32
(28) а всё равно (1) правильней, и такие универсальные не используются как правило
30 GANR
 
14.09.12
13:44
(29) >правильней
чем?
>такие универсальные не используются как правило
В типовых в модуле ОбщегоНазначения эти механизмы присутствуют.
31 vmv
 
14.09.12
13:45
(0) эта байда в БСП в обоих вариантах есть, причем идентикатор класса объекта метаданных там определяться через хмл-типизацию и англоязный аналог и это привильно
32 Maxus43
 
14.09.12
13:49
(30) просто по феншую это. религиозно правильно.
Как правило не сипользуется - не значит что вобще
33 Aleksey
 
14.09.12
13:50
(30) (16) из типовой БП 2.0
34 GANR
 
14.09.12
13:55
(32) (1) по феншую, (3) - по пьяни, (17) - по быстродействию.
(33) Верно. На больших конфигурациях это будет работать в десятки раз медленнее.
35 Reset
 
14.09.12
13:56
(34) Да нету там быстродействия
36 Reset
 
14.09.12
13:57
(28)

Процедура Третий(СсылкаНаОбъект)
   
   ПолноеИмяМетаданного = СсылкаНаОбъект.Метаданные().ПолноеИмя();
   ВидМетаданногоСтрокой = Лев(ПолноеИмяМетаданного, Найти(ПолноеИмяМетаданного, ".") - 1);
   
   Если ВидМетаданногоСтрокой = "Документ" Тогда
       
   ИначеЕсли ВидМетаданногоСтрокой = "Справочник" Тогда
   
   ИначеЕсли ВидМетаданногоСтрокой = "ПланВидовХарактеристик" Тогда
       
   ИначеЕсли ВидМетаданногоСтрокой = "ПланВидовРасчета" Тогда
       
   ИначеЕсли ВидМетаданногоСтрокой = "Задача" Тогда
       
   ИначеЕсли ВидМетаданногоСтрокой = "БизнесПроцесс" Тогда
       
   ИначеЕсли ВидМетаданногоСтрокой = "Перечисление" Тогда
       
   КонецЕсли;
   
КонецПроцедуры

Процедура Первый(СсылкаНаОбъект)
   
   Тип=ТипЗнч(СсылкаНаОбъект);
   Если Документы.ТипВсеСсылки().СодержитТип(Тип) Тогда    
       
   ИначеЕсли Справочники.ТипВсеСсылки().СодержитТип(Тип) Тогда    
       
   ИначеЕсли ПланыВидовХарактеристик.ТипВсеСсылки().СодержитТип(Тип) Тогда    
       
   ИначеЕсли ПланыВидовРасчета.ТипВсеСсылки().СодержитТип(Тип) Тогда    
       
   ИначеЕсли Задачи.ТипВсеСсылки().СодержитТип(Тип) Тогда    
       
   ИначеЕсли БизнесПроцессы.ТипВсеСсылки().СодержитТип(Тип) Тогда    
       
   ИначеЕсли Перечисления.ТипВсеСсылки().СодержитТип(Тип) Тогда    
       
   КонецЕсли;

КонецПроцедуры


СсылкаНаОбъект=Перечисления.ABCКлассификация.ПустаяСсылка();

Для i=1 по 100000 цикл Третий(СсылкаНаОбъект); конецЦикла;  // 1.966
Для i=1 по 100000 цикл Первый(СсылкаНаОбъект);  конецЦикла; // 3.057

СсылкаНаОбъект=Документы.ABCКлассификацияПокупателей.ПустаяСсылка();

Для i=1 по 100000 цикл Третий(СсылкаНаОбъект); конецЦикла;    // 1.651
Для i=1 по 100000 цикл Первый(СсылкаНаОбъект);  конецЦикла; // 1.058


Т.е. в неблагоприятных условиях стравнение строк выполняется быстрее, чем поиск (кто бы сомневался) а в благоприятных, напротив твоя ф-я медленней.
При этом метод через типы может работать с любым типом! Зачем при прочих равных выбирать менее надежный вариант?
37 Reset
 
14.09.12
13:58
И (29) прав, зачем универсальная? Чтоб потом опять строить кучу Если вокруг возвращенного значения?
38 GANR
 
14.09.12
14:25
(36) Это хороший анализ алгоритмов. Теперь можно ставить точку.
39 GANR
 
14.09.12
14:26
.