Динамический против Typed дает странные результаты - PullRequest
7 голосов
/ 26 мая 2011

У меня есть элемент управления SAP RPC OCX, который я хотел бы использовать.В C # 4 следующий код работает нормально:

System.Type t = System.Type.GetTypeFromProgID("SAP.Functions", true);            
dynamic fc = System.Activator.CreateInstance(t, false);
dynamic connection = fc.Connection;
connection.System = "";

Следующий код НЕ работает (даже если соединение НЕ пусто)

System.Type t = System.Type.GetTypeFromProgID("SAP.Functions", true);            
dynamic fc = System.Activator.CreateInstance(t, false);
var connection = fc.Connection as SAPLogonCtrl.Connection
connection.System = "";

Выдается следующая ошибка: «Попытка чтения или записиЗащищенная память. Это часто указывает на то, что другая память повреждена. "

Самый странный факт заключается в следующем:

System.Type t = System.Type.GetTypeFromProgID("SAP.Functions", true);            
dynamic fc = System.Activator.CreateInstance(t, false);
dynamic c1 = fc.Connection;
var c2 = fc.Connection as SAPLogonCtrl.Connection;
if (c1 == c2)
  c2.System = "";

Последняя строка выполняется и выдает то же исключение !!!Заменить с2 на с1 работает, как и ожидалось ...

Мне кажется, что я упускаю что-то тривиальное, и все же я в полной растерянности ... Пожалуйста, помогите?

Дополнительная информация: Изменение:

dynamic fc = System.Activator.CreateInstance(t, false);

до:

var fc = System.Activator.CreateInstance(t, false) as SAPFunctionsOCX.SAPFunctions;

Не имеет значения.c1 все еще работает, а c2 все еще не работает.

Дополнительная информация # 2: Изменение свойств на самом FC также работает в обоих случаях.

Ответы [ 4 ]

1 голос
/ 05 октября 2011

Хотя похоже, что вы оба раза делаете одно и то же, на самом деле все совершенно иначе: в первом примере кода:

dynamic connection = fc.Connection;
connection.System = "";

что происходит, если вы получаете fc.Connection, а затем вызываетеSystem = свойство setter с использованием dynamic.Динамическая языковая среда выполнения отключается, запрашивает интерфейсы COM и вызывает определенный метод для определенного интерфейса COM.На самом деле вы не можете увидеть, какой интерфейс или метод он использует со стороны C #.

Во втором примере (я заменил var, чтобы сделать вещи более понятными):

SAPLogonCtrl.Connection connection = fc.Connection as SAPLogonCtrl.Connection
connection.System = "";

что происходит, вы получаете fc.Connection, а затем приводите его к SAPLogonCtrl.Connection.Затем вы пытаетесь позвонить SAPLogonCtrl.Connection.System =, и тогда это не удается.

Я подозреваю, что это сбой, потому что объект на самом деле не является экземпляром SAPLogonCtrl.Connection, но это может быть прокси или какой-то другой объект.

Большая часть взаимодействия COM разделена на интерфейс (естьскорее всего SAPLogonCtrl.IConnection) и класс.При вызове методов обычно требуется вызывать через интерфейс .Код dynamic сделает все это за вас.

Вы можете попробовать поискать интерфейс и позвонить, используя это.Если в конечном итоге SAPLogonCtrl.IConnection существует, решение может быть следующим.

var connection = fc.Connection as SAPLogonCtrl.IConnection // note the I!
connection.System = "";

В любом случае, не забывайте вызывать через интерфейс при работе с COM-взаимодействием

0 голосов
/ 30 августа 2011

Просто идея, но так как динамический не привязан до времени выполнения, тогда как var связан во время компиляции, может ли быть тип fc недоступен для соединения?

РЕДАКТИРОВАТЬ: Как побочный вопрос, есть ли необходимость использовать:

var connection = fc.Connection as SAPLogonCtrl.Connection

Где вы могли бы просто использовать:

SAPLogonCtrl.Connection connection = fc.Connection;

Я что-то упустил? Зачем вам устанавливать его как неявный тип, а затем явно приводить его?

0 голосов
/ 21 сентября 2011

Вы должны понимать, что во время выполнения Dynamic запускается как Object, и Object может принимать все, что угодно. Этот простой факт отмечен в начале C # 4.0

Примечание. Необычно, динамический тип существует только во время компиляции; во время выполнения вместо этого используется тип System.Object. Это небольшая деталь реализации, но ее стоит запомнить, так как она может прояснить некоторые последующие обсуждения. Если у вас есть динамическая переменная, вы можете перейти к ее элементам (код для фактического получения значения для этой переменной здесь не показан): myDynamicVar.DoSomething («With this!»);

Уотсон, Карли; Нагель, Кристиан; Педерсен, Джейкоб Хаммер; Рейд, Джон Д .; Скиннер, Морган (2011-02-08). Начало работы с Visual C # 2010 (программист от Wrox до программиста) (стр. 414). Wrox. Kindle Edition.

0 голосов
/ 02 июня 2011

Можете ли вы не просто добавить фактический элемент управления в качестве ссылки на ваш проект и использовать его через код взаимодействия, который создает Visual Studio, вместо того, чтобы пытаться создать его с помощью COM и отражения?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...