Вопрос по windows-runtime – Каковы языковые прогнозы WinRT?

17

Что такое языковые проекции WinRT и для чего они используются?

Ваш Ответ

4   ответа
1

Windows без использования языков.

Например,лежащий в основе способ создатьWindows.Globalization.Calendar объект для вызова:

IInspectable instance;
HRESULT hr = RoActivateInstance(StringToHSTRING("Windows.Globalization.Calendar"), out instance);
if (Failed(hr))
   throw new ComException(hr);

ICalendar calendar;
hr = instance.QueryInterface(IID_ICalendar, out calendar);
if (Failed(hr))
   throw new ComException(hr);

Это то, что большинство языков называют"конструктор", Но большинство языков уже имеют синтаксис"создать объект".

Если вы находитесь в C #, у вас есть:

Calendar calendar = new Calendar();

Если вы в Паскале, у вас есть:

calendar: TCalendar;

calendar := TCalendar.Create;

Итак, давайте создадим C # -подобную оболочку (илипроекция) вокруг этого:

class Calendar : Object
{
   private ICalendar _calendar;

   //constructor
   void Calendar() : base()
   { 
      IInspectable instance;
      HRESULT hr = RoActivateInstance(StringToHSTRING("Windows.Globalization.Calendar"), out instance);
      if (Failed(hr))
         throw new ComException(hr);
      ICalendar calendar;
      hr = instance.QueryInterface(IID_ICalendar, out calendar);
      if (Failed(hr))
         throw new ComException(hr);

      this._calendar = calendar;
   }
}

И теперь вы можете использовать вашу дружественную C # -подобную проекцию:

Calendar cal = new Calendar();
Паскаль версия конструкторов

Допустим, вы используете Delphi: у вас уже есть идиома для создания объектов. Позволяет преобразовать основную сантехнику в дружественную проекцию Паскаля:

TCalendar = class
private
   FCalendar: ICalendar;
public
   constructor Create;
end;

constructor TCalendar.Create;
var
   instance: IInspectable;
   calendar: ICalendar;
   hr: HRESULT;
begin
   inherited Create;

   hr := RoActivateInstance(StringToHSTRING('Windows.Globalization.Calendar'), {out} instance);
   OleCheck(hr);

   hr = instance.QueryInterface(IID_ICalendar, {out} calendar);
   OleCheck(hr);

   FCalendar := calendar;
end;

И теперь у нас естьПроекция дельфи:

calendar: TCalendar;

calendar := TCalendar.Create;
свойства(используйте их, если у вас есть)

В основеICalendar интерфейс, вы должны получить и установить свойства с помощью методов:

get_Yearset_Year

Если вы слепо перевели это на C #, вы можете получить:

C # методы собственности:

class Calendar : Object
{
   private ICalendar _calendar;

   public int get_Year() { return _calendar.get_Year(); }
   void set_Year(int value) { _calendar.set_Year(value); }
}

паскаль методы собственности:

TCalendar = class
public
   function get_Year: Integer;
   procedure set_Year(Value: Integer);
end;

Но если ваш язык поддерживает их, вы на самом деледолжен выставить эти свойства как актуальные«Свойства», Таким образом, мы можем проецировать эти свойства, используя синтаксис свойства, свойственный нашему языку:

C #:

class Calendar : Object
{
   private ICalendar _calendar;

   public int Year { 
         get { return _calendar.get_Year(); } 
         set { _calendar.set_Year(value); }
   }
}

паскаль:

TCalendar = class
public
   property Year: Integer read get_Year write set_Year;
end;
итераторы

Идея состоит в том, чтобы создать фасад, который будет выглядеть и ощущаться как ваш язык, но за кулисами он сопоставляется с базовыми вызовами. Это идет довольно глубоко.

В WinRT все перечисляемое реализует

IIterable<T>

Но в C # все перечисляемое должно начинаться с:

IEnumerable

Таким образом, библиотека .NET имеет внутренний класс, который адаптируетIIterable<T> и выставляет его какIEnumerable.

Так что вместо метода, возвращающегоIIterable<T>:

class Calendar : Object
{
   public IIterable<Datetime> Holidays()
   {
      return _calendar.Holidays();
   }
}

ВозвращаетIEnumerable<T>:

class Calendar : Object
{
   public IEnumerable<DateTime> Holidays()
   {
       IIterable<DateTime> iter = _calendar.Holidays();

       //Create helper class to convert IIterable to IEnumerable
       IEnumerable<DateTime> enum = new IteratorToEnumeratorAdapter(iter);

       return enum;
   }
}

Таким образом, вы можете использовать свой собственный язык:

foreach date in Holidaysfor date in Holdays doЧто дата?

В WinRT даты представлены в видеWindows.Foundation.DateTime:

class Calendar : Object
{
   //Windows.Foundation.DateTime
   Datetime Date { get { return _calendar.get_Date(); } set { _calendar.set_Date(value); }
}

Но на других языках у нас уже есть свойДата и время классы:

C #: System.DateTimeOffsetJavascript: DateC ++: FILETIMEDelphi: TDateTime

Таким образом, проекция выполняет работу по конвертации WinRTDateTime (Int64 - число интервалов в 100 нс с 1 января 1601 г.) до C #DateTimeOffset:

class Calendar : Object
{
   //System.DateTimeOffset
   DateTimeOffset Date { 
       get { 
          Int64 ticks _calendar.get_Date().UniversalTime(); 
          DateTimeOffset dt = DateTimeOffset.FromFileTime(ticks);
          return dt;
       } 
       set { 
          Int64 ticks = value.ToFileTime();

          DateTime dt = new Windows.Foundation.DateTime();
          dt.UniversalTime = ticks;
          _calendar.set_Date(dt);
       }
}

и что-то похожее на Delphi'sTDateTime:

type
   TCalendar = class(TObject)
   private
      FCalendar: ICalendar;
      function getDate: TDateTime;
      procedure setDate(Value: TDateTime);
   public
      property Date: TDateTime read getDate write setDate;
   end;

   function TCalendar.GetDate: TDateTime;
   var
      ticks: Int64;
   const
      OA_ZERO_TICKS = Int64(94353120000000000);
      TICKS_PER_DAY = Int64(864000000000);
   begin
      ticks := FCalendar.get_Date().UniversalTime;
      Result := (ticks - OA_ZERO_TICKS) / TICKS_PER_DAY;
   end;

   procedure TCalendar.SetDate(Value: TDateTime);
   var
      ticks: Int64;
   const
      OA_ZERO_TICKS = Int64(94353120000000000);
      TICKS_PER_DAY = Int64(864000000000);
   begin
      ticks := (Value * TICKS_PER_DAY) + OA_ZERO_TICKS;
      FCalendar.set_Date(Round(ticks));
   end;    
ТЛ; др

Проекция - это набор оберток вокруг WinRT, чтобы он выглядел как можно ближе к вашему родному языку.

В C # никто на самом деле не пишет прогнозируемые версии; Компилятор и среда выполнения выполняют всю работу за кулисами, потому что они знают, как читать метаданные.

Для других языков переведенные файлы кода создаются вручную или автоматически с помощью инструмента импорта.

10

Языковые проекции WinRT - это привязки WinRT для каждого поддерживаемого языка.

Для получения дополнительной информации, проверьте:

WinRT Демистифицировано - Мигель де Икаса

Одно тонкое отличие состоит в том, что «привязки» могут быть ручными, в то время как «проекции» всегда автоматизированы - то есть вы не сидите там вручную и пишете декларации FFI для WinRT с проекцией, вы просто используете код, написанный один раз, который принимает любой компонент WinRT и выставляет его на соответствующий язык, используя идиомы этого языка. Pavel Minaev
4

я «внешним интерфейсом», тогда как среда выполнения Windows является внутренним. Пишите на одном из трех языков (JS, C #, VB), он ведет себя одинаково на серверной части.

Если вы пишете свой собственный сторонний компонент WinRT на C ++ или C #, вы можете использовать его из JS, C # и VB, не выполняя никакой дополнительной работы.

12

выполнения Windows на каждом языке. Это может быть во время компиляции (как в C ++) или во время выполнения (как в JavaScript) или в комбинации (как в C #). Каждый язык решает, как лучше всего представить API WinRT. В большинстве случаев это прямое воздействие, но в других случаях возможны обертки или перенаправления. Делегаты и мероприятия являются хорошим примером. В C # они отображаются как делегаты / события C #, а не как типы, специфичные для WinRT. Строки также преобразуются в строковый тип на родном языке, а не в базовый тип hstring.

Похожие вопросы