РЕДАКТИРОВАТЬ: я написал результаты в виде сообщения в блоге .
Компилятор C # обрабатывает COM-типы магическим образом. Например, это утверждение выглядит нормально ...
Word.Application app = new Word.Application();
... пока не поймешь, что Application
это интерфейс. Вызов конструктора для интерфейса? Йойку! Это на самом деле переводится в вызов Type.GetTypeFromCLSID()
и другой Activator.CreateInstance
.
Кроме того, в C # 4 вы можете использовать не-ref аргументы для ref
параметров, и компилятор просто добавляет локальную переменную для передачи по ссылке, отбрасывая результаты:
// FileName parameter is *really* a ref parameter
app.ActiveDocument.SaveAs(FileName: "test.doc");
(Да, здесь отсутствует куча аргументов. Разве необязательные параметры хороши? :)
Я пытаюсь исследовать поведение компилятора, и мне не удается подделать первую часть. Я могу сделать вторую часть без проблем:
using System;
using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;
[ComImport, GuidAttribute("00012345-0000-0000-0000-000000000011")]
public interface Dummy
{
void Foo(ref int x);
}
class Test
{
static void Main()
{
Dummy dummy = null;
dummy.Foo(10);
}
}
Я хотел бы иметь возможность написать:
Dummy dummy = new Dummy();
хотя. Очевидно, что во время исполнения все будет хорошо, но ничего страшного. Я просто экспериментирую.
Другие атрибуты, добавленные компилятором для связанных COM PIA ( CompilerGenerated
и TypeIdentifier
), похоже, не работают ... что за волшебный соус?
источник
dynamic
... мы просто слишком привыкли к статической / строгой типизации, чтобы понять, почему это важно вне COM.Ответы:
Я ни в коем случае не эксперт в этом, но недавно я наткнулся на то, что, как мне кажется, вы хотите: класс атрибутов CoClass .
Посмотрите мой ответ на похожий вопрос о Microsoft Speech API , где вы можете «создать экземпляр» интерфейса
SpVoice
(но на самом деле вы его создаетеSPVoiceClass
).источник
Между тобой и Майклом у тебя почти есть все воедино. Я думаю, что это так. (Я не писал код, поэтому, возможно, я немного ошибочно его излагаю, но я почти уверен, что так оно и есть).
Если:
затем код генерируется как (IPIAINTERFACE) Activator.CreateInstance (Type.GetTypeFromClsid (GUID OF COCLASSTYPE))
Если:
тогда код генерируется так, как если бы вы сказали «новый COCLASSTYPE ()».
Джон, не стесняйся задавать мне или Сэму напрямую, если у тебя есть вопросы по этому поводу. К вашему сведению, Сэм - эксперт по этой функции.
источник
Хорошо, это просто для того, чтобы придать ответу Майкла немного больше (он может добавить его, если захочет, и в этом случае я удалю этот).
Глядя на оригинальную PIA для Word.Application, можно выделить три типа (игнорируя события):
Есть два интерфейса по причинам, о которых говорит Эрик Липперт в другом ответе . И, как вы сказали, есть
CoClass
- и с точки зрения самого класса, и с точки зрения атрибутаApplication
интерфейса.Теперь, если мы используем связывание PIA в C # 4, часть этого будет встроена в получившийся двоичный файл ... но не все. Приложение, которое просто создает экземпляр,
Application
заканчивается этими типами:Нет
ApplicationClass
- предположительно потому что это будет загружаться динамически из реального типа COM во время выполнения.Еще одна интересная вещь - это разница в коде между связанной версией и несвязанной версией. Если вы декомпилируете строку
в ссылочной версии это заканчивается как:
тогда как в связанной версии это заканчивается как
Так это выглядит , как «реальный» PIA нужен
CoClass
атрибут, но связанная версия не потому , что неCoClass
компилятор может на самом деле ссылка. Это должно делать это динамически.Я мог бы попытаться подделать COM-интерфейс, используя эту информацию, и посмотреть, смогу ли я заставить компилятор связать его ...
источник
Просто добавлю немного подтверждения к ответу Майкла:
Следующий код компилируется и запускается:
Вам нужно и то,
ComImportAttribute
иGuidAttribute
это для работы.Также обратите внимание на информацию, когда вы наводите курсор мыши на
new IFoo()
: Intellisense правильно подбирает информацию: Nice!источник