windows runtime - para - ¿Qué son las proyecciones de lenguaje WinRT?
universal c runtime windows 7 (4)
"Proyecciones" en WinRT es otra palabra para "Encuadernaciones".
Las proyecciones de idioma de WinRT son los enlaces de WinRT para cada idioma compatible.
Para más información, echa un vistazo a:
¿Qué son las proyecciones de lenguaje WinRT y para qué se usan?
La forma más sencilla de aclarar es que una proyección de lenguaje en WinRT es el "front end", mientras que el tiempo de ejecución de Windows es el backend. Escriba desde uno de los tres idiomas (JS, C #, VB), se comporta de manera idéntica en el extremo posterior.
Si escribe su propio componente de WinRT de terceros en C ++ o C #, puede usarlo desde JS, C # y VB sin tener que hacer ningún trabajo adicional.
Las proyecciones de Windows Runtime son la forma en que las API de Windows Runtime están expuestas en cada idioma. Esto puede ser en tiempo de compilación (como en C ++) o en tiempo de ejecución (como en JavaScript) o una combinación (como en C #). Cada idioma decide cómo presentar mejor las API de WinRT. La mayoría de las veces es una exposición directa, pero otras veces hay envolturas o redirecciones que pueden tener lugar. Los delegados y eventos son un buen ejemplo. En C # se muestran como delegados / eventos de C # y no como tipos específicos de WinRT. Las cadenas también se vuelven a asignar para que sean el tipo de cadena del idioma nativo y no el tipo de cadena subyacente.
Una proyección de idioma es una forma de exponer la API de Windows Runtime de manera amigable con el idioma.
Por ejemplo, la forma subyacente de crear un objeto Windows.Globalization.Calendar es llamar:
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);
Eso es lo que la mayoría de los lenguajes llamaría un "constructor" . Pero la mayoría de los idiomas ya tienen una sintaxis para "crear un objeto" .
Si estás en C # tienes:
Calendar calendar = new Calendar();
Si estás en Pascal tienes:
calendar: TCalendar;
calendar := TCalendar.Create;
Así que vamos a crear una envoltura similar a C # (o proyección ) alrededor de esto:
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;
}
}
Y ahora puedes usar tu simpática proyección en C #:
Calendar cal = new Calendar();
Pascal version de constructores.
Digamos que estás usando Delphi: ya tienes un modismo para crear objetos. Permite convertir la tubería subyacente en una proyección amigable de Pascal:
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;
Y ahora tenemos nuestra proyección de Delphi :
calendar: TCalendar;
calendar := TCalendar.Create;
Propiedades (usarlas si las tienes)
En la interfaz de ICalendar
subyacente, debe obtener y establecer propiedades mediante los métodos:
- get_Year
- set_Year
Si lo tradujeras ciegamente a C # podrías obtener:
Métodos de propiedad C # :
class Calendar : Object
{
private ICalendar _calendar;
public int get_Year() { return _calendar.get_Year(); }
void set_Year(int value) { _calendar.set_Year(value); }
}
Métodos de propiedad de Pascal :
TCalendar = class
public
function get_Year: Integer;
procedure set_Year(Value: Integer);
end;
Pero si su idioma los admite, debería exponer estas propiedades como "Propiedades" reales. Así que podemos proyectar estas propiedades utilizando la sintaxis de propiedad nativa de nuestro idioma:
C # :
class Calendar : Object
{
private ICalendar _calendar;
public int Year {
get { return _calendar.get_Year(); }
set { _calendar.set_Year(value); }
}
}
Pascal :
TCalendar = class
public
property Year: Integer read get_Year write set_Year;
end;
ITeradores
La idea es crear una fachada que se vea y se sienta como su idioma, pero detrás de escena se asigna a las llamadas subyacentes. Va bastante profundo.
En WinRT, todo lo que son implementos enumerables.
-
IIterable<T>
Pero en C #, todo enumerable se supone que debe comenzar desde:
-
IEnumerable
Por lo tanto, la biblioteca .NET tiene una clase interna que adapta un IIterable<T>
y lo expone como un IEnumerable
.
Así que en lugar de un método que devuelve un IIterable<T>
:
class Calendar : Object
{
public IIterable<Datetime> Holidays()
{
return _calendar.Holidays();
}
}
Devuelve un 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;
}
}
De esta manera puedes usar el idioma de tu idioma:
-
foreach date in Holidays
-
for date in Holdays do
¿Cuál es la fecha?
En el WinRT, las fechas se representan como Windows.Foundation.DateTime
:
class Calendar : Object
{
//Windows.Foundation.DateTime
Datetime Date { get { return _calendar.get_Date(); } set { _calendar.set_Date(value); }
}
Pero en otros idiomas, ya tenemos nuestras propias clases de fecha y hora :
- C # :
System.DateTimeOffset
- Javascript :
Date
- C ++ :
FILETIME
- Delphi :
TDateTime
Así que la proyección hace el trabajo de convertir WinRT DateTime
(un Int64 que es el número de intervalos de 100 ns desde el 1 de enero de 1601) a un 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);
}
}
y algo similar a TDateTime de Delphi :
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;
tl; dr
Una proyección es un conjunto de envoltorios alrededor de WinRT para que se vea lo más parecido posible a su idioma nativo.
En C #, nadie escribe las versiones proyectadas; El compilador y el tiempo de ejecución hacen todo el trabajo detrás de escena porque sabe cómo leer los metadatos.
Para otros idiomas, los archivos de códigos traducidos se crean manual o automáticamente mediante una herramienta de importación.