Здравствуйте, уважаемые жители этого форума.
Я тут впервые, но со сложным (для меня) вопросом.
Пишу я на C# свой COM. Всё впорядке, но за исключением того, что не могу использовать индексаторы в полной мере. Например: объект myCom.obj[2] или myCom.obj(2) (взависимости от языка) я не могу получить.
Хотя выполняю правильно регистрацию, создаю интерфейсы, присваиваю guid, свойству с индексатором в интерфейсе ставлю аттрибут [DispId(0)], как положено. Но это свойство почему-то правильно работает, только если его вызвать его непосредственно у com объекта:
myCom[0] или myCom(0) (если в моем интерфейсе конечно объявлено свойство с индексатором).
А вот если пойти дальше по иерархии, то уже никак...
Помогите пожалуйста с этой проблемой или можно просто дать работающий пример.
Спасибо заранее!
Re: COM на C#. Не могу получить объект из коллекции.
Здравствуйте, sashar2, Вы писали:
S>Пишу я на C# свой COM. Всё впорядке, но за исключением того, что не могу использовать индексаторы в полной мере. Например: объект myCom.obj[2] или myCom.obj(2) (взависимости от языка) я не могу получить. S>Хотя выполняю правильно регистрацию, создаю интерфейсы, присваиваю guid, свойству с индексатором в интерфейсе ставлю аттрибут [DispId(0)], как положено. Но это свойство почему-то правильно работает, только если его вызвать его непосредственно у com объекта: myCom[0] или myCom(0) (если в моем интерфейсе конечно объявлено свойство с индексатором).
Это правильно — индексатор работает с объектом.
S>А вот если пойти дальше по иерархии, то уже никак...
Куда дальше? Сделать myCom.obj[2] как (myCom.obj)[2]? Для этого объект myCom.obj должен в свою очередь обладать индексатором.
Приведите пожалуйста работающий пример, где можно было бы обратиться через индексатор к свойству ком объекта (как я уже приводил пример myCom.obj(2)). Очень нужно...
Re[4]: COM на C#. Не могу получить объект из коллекции.
Здравствуйте, sashar2, Вы писали:
S>Приведите пожалуйста работающий пример, где можно было бы обратиться через индексатор к свойству ком объекта (как я уже приводил пример myCom.obj(2)). Очень нужно...
Непонятны затруднения. Может, тебя интересует myCom(2).obj — обращение к свойству "obj" объекта myCom(2)?
Здравствуйте, Vi2, Вы писали:
Vi2>Здравствуйте, sashar2, Вы писали:
S>>Приведите пожалуйста работающий пример, где можно было бы обратиться через индексатор к свойству ком объекта (как я уже приводил пример myCom.obj(2)). Очень нужно...
Vi2>Непонятны затруднения. Может, тебя интересует myCom(2).obj — обращение к свойству "obj" объекта myCom(2)?
Затруднения в том, что не получается в другом языке создать ком объект и получить объект из коллекции, как например — ком объект — MyCom, у него есть коллекция Obj, к элементу этой коллекции я не могу обратиться как MyCom.Obj(2), только если MyCom.Obj.Item(2). Хотя если у самого ком объекта есть коллекция (например обратиться как MyCom[2]), то все получается.
Если не затруднит, то пожалуйста приведите пример. Он всего занимает несколько строк, но я пойму в чем я ошибался.
Re[6]: COM на C#. Не могу получить объект из коллекции.
В С++ я получал из указателя на интерфейс ком объект ком, таким образом там все работало. В C# же такое сделать, как я понимаю (про это была уже такая тема) сделать нельзя: http://rsdn.ru/Forum/message/124975.flat.aspx
Здравствуйте, Vi2, Вы писали:
Vi2>Здравствуйте, sashar2, Вы писали:
S>>Приведите пожалуйста работающий пример, где можно было бы обратиться через индексатор к свойству ком объекта (как я уже приводил пример myCom.obj(2)). Очень нужно...
Vi2>Непонятны затруднения. Может, тебя интересует myCom(2).obj — обращение к свойству "obj" объекта myCom(2)?
Тоже стало интересно.
В чем дело не знаю, но попробую объяснить проблему. Если я правильно понял, то имеем
namespace ClassLibrary1
{
public class Class1
{
public ArrayList objs
{
get
{
return new ArrayList(new object[] { "a", "b", "c"});
}
}
}
}
теперь используем это (VB script):
Set c = CreateObject("ClassLibrary1.Class1")
a = c.objs.Item(1) ' <- так работает
a = c.objs(1) ' <- так не работает (*) - "недопустимое число аргументов или присвоение свойства"Set objs = c.objs
a = objs(1) ' <- так работаетfor each (obj in c.objs) ' <- так тоже работает
Вопрос — почему (*) не работает и как сделать чтобы работала?
Re[6]: COM на C#. Не могу получить объект из коллекции.
Здравствуйте, bnk, Вы писали:
bnk>a = c.objs.Item(1) ' <- так работает bnk>a = c.objs(1) ' <- так не работает (*) — "недопустимое число аргументов или присвоение свойства"
Потому что это вызов у объекта "c" метода "objs" с параметром "1". Скорее всего, нужно в этом методе предусмотреть необязательный параметр и отрабатывать его соответственно: если есть, то возвращать i-ый объект коллекции, если нет, то возвращать саму коллекцию. Если это неприемлимо, то тогда и решения нет.
PS
Кстати, те языки, которые понимают Библиотеку типов, должны правильно разруливать вызовы и должны отработать по сценарию (c.objs)(1).
Здравствуйте, Vi2, Вы писали:
Vi2>Потому что это вызов у объекта "c" метода "objs" с параметром "1". Скорее всего, нужно в этом методе предусмотреть необязательный параметр и отрабатывать его соответственно: если есть, то возвращать i-ый объект коллекции, если нет, то возвращать саму коллекцию. Если это неприемлимо, то тогда и решения нет.
Vi2>PS Vi2>Кстати, те языки, которые понимают Библиотеку типов, должны правильно разруливать вызовы и должны отработать по сценарию (c.objs)(1).
IMHO тут должен быть какой-то трюк (для экселя вот это например вполне работает):
Тот же VB script:
Set e = CreateObject("Excel.Application")
e.Workbooks.Add
Set a = e.Worksheets(1) ' <- все ОК (хотя библиотеки типов нет)Set c = CreateObject("ClassLibrary1.Class1")
Set a = c.objs(1) ' <- Oops !
Кажется Excel добавляет к коллекции метод _Default(VARIANT) c DispId=0
Re[8]: COM на C#. Не могу получить объект из коллекции.
Здравствуйте, bnk, Вы писали:
bnk>IMHO тут должен быть какой-то трюк (для экселя вот это например вполне работает): bnk>Тот же VB script:
bnk>Set e = CreateObject("Excel.Application")
bnk>e.Workbooks.Add
bnk>Set a = e.Worksheets(1) ' <- все ОК (хотя библиотеки типов нет)
bnk>Set c = CreateObject("ClassLibrary1.Class1")
bnk>Set a = c.objs(1) ' <- Oops !
bnk>Кажется Excel добавляет к коллекции метод _Default(VARIANT) c DispId=0
Это не имеет значение, поскольку для ClassLibrary1.Class1 его метод "objs" можно реализовать так, чтобы он возвращал стандартную коллекцию, у которой тоже есть свойство по умолчанию, или же задать у коллекции явно признак Default.
Есть два объяснения феномену.
1) При вызове e.Worksheets(1) по схеме "свойство-с-параметром" через IDispatch::Invoke разработчики сервера Excel часто встречались с такой ситуацией (с таким обращением к свойству) и реализовали специальную обработку при наличии параметра.
2) При вызове e.Worksheets(1) скрипт (управляющая среда) получает ошибку с кодом "Неверное количество аргументов" и редуцирует вызов до e.Worksheets с последующим обращением к дефолтному методу полученного(ых) объекта(ов).
Здравствуйте, Vi2, Вы писали:
Vi2>Есть два объяснения феномену. Vi2>1) При вызове e.Worksheets(1) по схеме "свойство-с-параметром" через IDispatch::Invoke разработчики сервера Excel часто встречались с такой ситуацией (с таким обращением к свойству) и реализовали специальную обработку при наличии параметра.
Vi2>2) При вызове e.Worksheets(1) скрипт (управляющая среда) получает ошибку с кодом "Неверное количество аргументов" и редуцирует вызов до e.Worksheets с последующим обращением к дефолтному методу полученного(ых) объекта(ов).
Посмотрел TLB excel-я, там _Default — это проперти с параметром VARIANT и DispId=0
Так что пример должен разбираться как
e.Worksheets._Default(idx)
Но неясно как это сделать на C#.
Т.е. чтобы заработало надо примерно вот это (IDL), но на C# это похоже невозможно? (т.е. propget c параметром)?