什么是WinRT语言预测?

Alf*_*ers 17 windows-runtime

什么是WinRT语言预测以及它们用于什么?

Ste*_*owe 12

Windows运行时预测是以每种语言公开Windows运行时API的方式.这可能是在编译时(如在C++中)或在运行时(如在JavaScript中)或组合(如在C#中).每种语言都决定如何最好地呈现WinRT API.大多数情况下,它是直接暴露,但有时可能会发生包装或重定向.代表和活动就是一个很好的例子.在C#中,它们显示为C#委托/事件,而不是特定于WinRT的类型.字符串同样被重新映射为本机语言字符串类型,而不是底层的hstring类型.


Jus*_*ner 10

WinRT中的"预测"是"绑定"的另一个词.

WinRT语言预测是支持的每种语言的WinRT绑定.

有关更多信息,请查看:

WinRT揭秘 - Miguel de Icaza

  • 一个微妙的区别是"绑定"可以是手动的,而"投影"总是自动化的 - 即你不是手动编写WinRT的FFI声明用投影编写,你只需使用一次编写的代码,它需要任何WinRT组件并使用该语言的习语将其暴露于相关语言. (3认同)

Ian*_*oyd 10

语言投影是一种以语言友好的方式向您公开 Windows 运行时 API 的方法。

例如,创建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);
Run Code Online (Sandbox Code Playgroud)

这就是大多数语言所称的“构造函数”但大多数语言已经有了“创建对象”的语法。

如果您使用 C#,您将拥有:

Calendar calendar = new Calendar();
Run Code Online (Sandbox Code Playgroud)

如果您在帕斯卡,您将拥有:

calendar: TCalendar;

calendar := TCalendar.Create;
Run Code Online (Sandbox Code Playgroud)

因此,让我们围绕此创建一个类似 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;
   }
}
Run Code Online (Sandbox Code Playgroud)

现在您可以使用友好的类似 C# 的投影:

Calendar cal = new Calendar();
Run Code Online (Sandbox Code Playgroud)

帕斯卡版本的构造函数

假设您正在使用 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;
Run Code Online (Sandbox Code Playgroud)

现在我们有了Delphi 投影

calendar: TCalendar;

calendar := TCalendar.Create;
Run Code Online (Sandbox Code Playgroud)

属性(如果你有的话就使用它们)

在底层ICalendar接口中,您必须使用方法获取和设置属性:

  • 获取年份
  • 设置年份

如果你盲目地将其转换为 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); }
}
Run Code Online (Sandbox Code Playgroud)

帕斯卡性质方法:

TCalendar = class
public
   function get_Year: Integer;
   procedure set_Year(Value: Integer);
end;
Run Code Online (Sandbox Code Playgroud)

但如果您的语言支持它们,您实际上应该将这些属性公开为实际的“Properties”。因此,我们可以使用我们语言本身的属性语法来投影这些属性:

C#

class Calendar : Object
{
   private ICalendar _calendar;

   public int Year { 
         get { return _calendar.get_Year(); } 
         set { _calendar.set_Year(value); }
   }
}
Run Code Online (Sandbox Code Playgroud)

帕斯卡

TCalendar = class
public
   property Year: Integer read get_Year write set_Year;
end;
Run Code Online (Sandbox Code Playgroud)

迭代器

这个想法是创建一个看起来和感觉都像您的语言的外观,但在幕后它映射回底层调用。它很深。

在 WinRT 中,所有可枚举的东西都实现了

  • IIterable<T>

但在 C# 中,所有可枚举的内容都应该从以下位置开始:

  • IEnumerable

因此 .NET 库有一个内部类,它可以适应IIterable<T>并将其公开为IEnumerable.

因此,而不是返回一个方法IIterable<T>

class Calendar : Object
{
   public IIterable<Datetime> Holidays()
   {
      return _calendar.Holidays();
   }
}
Run Code Online (Sandbox Code Playgroud)

它返回一个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;
   }
}
Run Code Online (Sandbox Code Playgroud)

这样你就可以使用你自己的语言:

  • foreach date in Holidays
  • for 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); }
}
Run Code Online (Sandbox Code Playgroud)

但在其他语言中,我们已经有了自己的日期时间类:

  • C#System.DateTimeOffset
  • JavaScriptDate
  • C++FILETIME
  • 德尔福TDateTime

因此,投影会将 WinRT DateTime(Int64,即自 1601 年 1 月 1 日以来的 100 纳秒间隔数)转换为 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);
       }
}
Run Code Online (Sandbox Code Playgroud)

和 Delphi 的TDateTime类似:

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;    
Run Code Online (Sandbox Code Playgroud)

太长了;博士

投影是 WinRT 的一组包装器,使其看起来尽可能像您的母语。

在 C# 中,没有人真正编写预计的版本;编译器和运行时在幕后完成所有工作,因为它知道如何读取元数据。

对于其他语言,翻译后的代码文件是手动创建的,也可以通过导入工具自动创建。


Zac*_*SFT 5

最简单的澄清方法是,WinRT 中的语言投影是“前端”,而 Windows 运行时是后端。使用三种语言(JS、C#、VB)之一编写,它在后端的行为相同。

如果您使用 C++ 或 C# 编写自己的第 3 方 WinRT 组件,则可以从 JS、C# 和 VB 使用它,而无需执行任何额外工作。