Как компилятор C # обнаруживает типы COM?

EDIT: Я записал результаты какСообщение блога.

Компилятор 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Кажется, что не получается ... что за волшебный соус?

 Jon Skeet07 июл. 2009 г., 19:27
@Mehrdad: Дополнительные параметры полезны помимо COM, конечно. Вы должны быть осторожны со значениями по умолчанию, но между ними и именованными аргументами гораздо проще создать пригодный для использования неизменяемый тип.
 Mehrdad Afshari07 июл. 2009 г., 19:13
Не являются ли необязательные параметры хорошими? ИМО, нет они не хорошие. Microsoft пытается исправить ошибку в интерфейсах Office COM, добавив в C # раздувание.
 chakrit04 янв. 2011 г., 06:09
Я видел, как разработчики фреймворка начали обсуждать его использование во многих местах. IMO, это просто время, пока мы не найдем хорошее применение дляdynamic ... мы слишком привыкли к статической / строгой типизации, чтобы понять, почему это важно вне COM.
 Jon Skeet07 июл. 2009 г., 22:10
Я согласен, что команде нужно будет внимательно следить за сложностью. Динамический материал добавляет много сложности для небольшого значения дляmost разработчики, но большое значение дляsome Разработчики.
 Mehrdad Afshari07 июл. 2009 г., 22:08
Правда. В частности, именованные параметры могут бытьpractically required для взаимодействия с некоторыми динамическими средами. Конечно, без сомнения, это полезная функция, но это не значит, что она предоставляется бесплатно. Это стоит простоты (явно заявленная цель дизайна). Лично я думаю, что C # поразителен возможностями, которые команда прекратила (в противном случае это мог быть клон C ++). Команда C # великолепна, но корпоративная среда вряд ли может быть свободной от политики. яguess Сам Андерс не был очень доволен этим, как он заявил в своем выступлении на PDC'08: «Нам потребовалось десять лет, чтобы вернуться туда, где мы были».

Ответы на вопрос(4)

Решение Вопроса

но я недавно наткнулся на то, что, как мне кажется, вы хотите:CoClass Атрибут класса.

[System.Runtime.InteropServices.CoClass(typeof(Test))]
public interface Dummy { }

A coclass supplies concrete implementation(s) of one or more interfaces. In COM, such concrete implementations can be written in any programming language that supports COM component development, e.g. Delphi, C++, Visual Basic, etc.

Увидетьмой ответ на аналогичный вопрос о Microsoft Speech APIгде вы можете "создать экземпляр" интерфейсSpVoice (но на самом деле вы создаетеSPVoiceClass).

[CoClass(typeof(SpVoiceClass))]
public interface SpVoice : ISpeechVoice, _ISpeechVoiceEvents_Event { }
 10 июл. 2009 г., 18:16
+1 за то, что был крут, написав принятый ответ, когда Эрик Липперт и Джон Скит также ответили;) Нет, действительно, +1 за упоминание CoClass.
 Jon Skeet07 июл. 2009 г., 19:30
Очень интересно - попробую позже. Связанные типы PIA не имеют CoClass. Может быть, это как-то связано с процессом связывания - я взгляну на оригинальную PIA ...

Следующий код компилируется и запускается:

public class Program
{
    public class Foo : IFoo
    {
    }

    [Guid("00000000-0000-0000-0000-000000000000")]
    [CoClass(typeof(Foo))]
    [ComImport]
    public interface IFoo
    {
    }

    static void Main(string[] args)
    {
        IFoo foo = new IFoo();
    }
}

Вам нужны обаComImportAttribute иGuidAttribute чтобы это работало.

Также обратите внимание на информацию, когда вы наводите курсор мыши наnew IFoo(): Intellisense правильно подхватывает информацию: приятно!

 11 нояб. 2015 г., 16:07
спасибо, я пытался, но я скучалComImport атрибут, но когда я иду к исходному коду, я работал, используя только F12 показываетCoClass а такжеGuid, это почему?

что это так. (Я не писал код, поэтому, возможно, я немного ошибочно его формулирую, но я уверен, что так оно и есть).

Если:

you are "new"ing an interface type, and the interface type has a known coclass, and you ARE using the "no pia" feature for this interface

затем код генерируется как (IPIAINTERFACE) Activator.CreateInstance (Type.GetTypeFromClsid (GUID OF COCLASSTYPE))

Если:

you are "new"ing an interface type, and the interface type has a known coclass, and you ARE NOT using the "no pia" feature for this interface

затем код генерируется так, как если бы вы сказали «новый COCLASSTYPE ()».

Джон, не стесняйся задавать мне или Сэму напрямую, если у тебя есть вопросы по этому поводу. К вашему сведению, Сэм - эксперт по этой функции.

это просто для того, чтобы придать ответу Майкла немного больше (он может добавить его, если захочет, и в этом случае я удалю этот).

Глядя на оригинальную PIA для Word.Application, можно выделить три типа (игнорируя события):

[ComImport, TypeLibType(...), Guid("..."), DefaultMember("Name")]
public interface _Application
{
     ...
}

[ComImport, Guid("..."), CoClass(typeof(ApplicationClass))]
public interface Application : _Application
{
}

[ComImport, ClassInterface(...), ComSourceInterfaces("..."), Guid("..."), 
 TypeLibType((short) 2), DefaultMember("Name")]
public class ApplicationClass : _Application, Application
{
}

Есть два интерфейса по причинам, о которых говорит Эрик Липперт вдругой ответ, И там, как вы сказали, естьCoClass - как с точки зрения самого класса и атрибута наApplication интерфейс.

Теперь, если мы используем связывание PIA в C # 4,some это встроено в получившийся двоичный файл ... но не все. Приложение, котороеjust создает экземплярApplication заканчивается этими типами:

[ComImport, TypeIdentifier, Guid("..."), CompilerGenerated]
public interface _Application

[ComImport, Guid("..."), CompilerGenerated, TypeIdentifier]
public interface Application : _Application

нетApplicationClass - предположительно, потому что это будет загружаться динамически изreal Тип COM во время выполнения.

Другая интересная вещь - это разница в коде между связанной версией и несвязанной версией. Если вы декомпилируете строку

Word.Application application = new Word.Application();

вreferenced версия это заканчивается как:

Application application = new ApplicationClass();

тогда как вlinked версия это заканчивается как

Application application = (Application) 
    Activator.CreateInstance(Type.GetTypeFromCLSID(new Guid("...")));

Таким образом, это выглядит как "реальный" ПИЯ нужнаCoClass атрибут, но связанная версия не имеетisn't CoClass на самом деле компилятор может ссылаться. Это должно делать это динамически.

Я мог бы попытаться подделать COM-интерфейс, используя эту информацию, и посмотреть, смогу ли я заставить компилятор связать его ...

Ваш ответ на вопрос