Главная
Блог разработчиков phpBB
 
+ 17 предустановленных модов
+ SEO-оптимизация форума
+ авторизация через соц. сети
+ защита от спама

Windows Runtime. Система типов и взаимодействие с CLR

Anna | 17.06.2014 | нет комментариев
С выходом Windows 8 разработчикам стала доступна новая библиотека классов — Windows Runtime. Компоненты WinRT могут применяться в приложениях Windows Store и настольных приложениях; в неуправляемом коде C/C , в JavaScript, а также в C# и Visual Basic.

Метаданные Windows Runtime

На внутреннем ярусе компоненты WinRT представляют собой компоненты COM (Component Object Model), для изложения API которых сейчас применяются метаданные. Эти метаданные хранятся в файлах с растяжением *.winmd и представляют собой обновленную версию метаданных .NET, которые кодируются в соответствие с правилами раздела №2 (Metadata Definition and Semantics) эталона ECMA-335. От того что обыкновенные сборки .NET Framework кодируются с поддержкой этого же эталона, это говорит о том, что вы можете применять знакомые средства (такие как ildasm.exe, Object Browser) для просмотра содержимого этих файлов.
По большей части, просмотр WinMD файла с поддержкой утилиты ildasm.exe дюже схож на просмотр стандартной управляемой сборки. Есть несколько отличий, которые могут быть видны — в первую очередь то, что WinMD файлы, в всеобщем, не содержат никаких Intermediate Language (IL) инструкций. Взамен этого, эти файлы описывают API, предоставляемые Windows Runtime. Реализация этих интерфейсов может быть всецело отделена от их определения, и по сути, может быть записана в машинном коде. Тем не менее, для разработчиков управляемых приложений, детали реализации WinRT API не имеют значения, потому что управляемый код должен видеть только определения API, которые он вызывает. За кулисами, Common Language Runtime (CLR) и операционная система Windows соединяют для вас определения API и их реализации.

Скажем, в файле метаданных Windows.Foundation.winmd (находится в каталоге %WinDir%\System32\WinMetadata) вы можете найти дальнейший тип Windows.Foundation.Collections.PropertySet, конструктор которого не содержит тела, потому что тип реализуется в native code.

image

Тем не менее, метаданные, которые описывают данный тип разрешают CLR получить экземпляр реализации при вызове конструктора класса.
При просмотре Windows Runtime метаданных дозволено также подметить, что определения типов и сборок применяют новое ключевое слово WindowsRuntime.

image

Это ключевое слово является контекстно-зависимым и по различному интерпретируется в зависимости от того, где оно используется. Скажем, если ключевым словом помечено определение типа (TypeDef), то данный тип подчиняется правилам системы типов Windows Runtime и вызов этого типа следует рассматривать как вызов WinRT API.

Взаимодействие CLR с компонентами WinRT

CRL поддерживает взаимодействие с COM-компонентами через обертки Runtime Callable Wrapper (RCW) и COM Callable Wrapper (CCW). Таким образом в CLR ссылка на WinRT объект представляет собой ссылку на RCW, которая в свою очередь содержит ссылку на WinRT объект. Соответственно управляемый код взаимодействует с RCW, тот, что по сути является интерфейсом между вашим кодом и WinRT объектом.

image

Аналогичным образом в Windows Runtime ссылка на объект CLR представляет собой ссылку на CCW, которая в свою очередь содержит ссылку на CLR объект. Windows Runtime при этом взаимодействует с CCW для доступа к функциональности управляемого объекта.

WinRT типы и управляемый код

Невзирая на то, что система типов Windows Runtime схожа с системой типов CLR, при внимательном просмотре WinMD файлов дозволено подметить, что некоторые из типов, испоment> обновлен средой CLR. Реализация интерфейса IVector<T> перенаправляется на IList<T> так, что UIElementCollection в управляемом коде реализует интерфейс IList<UIElement>.
Традиционно ildasm.exe показывает необработанное представление файла WinMD без включения всяких перенаправлений. Дабы просмотреть содержимое файла WinMD с включенными перенаправлениями, следует указать параметр /project. Эта опция разрешает увидеть, как CLR отображает метаданные на диске.

Базовый тип

Компоненты WinRT не имеют всеобщего базового класса, впрочем все классы среды выполнения Windows обязаны реализовывать интерфейс IInspectable, тот, что в свою очередь наследует от интерфейса IUnknown(что не изумительно). Впрочем, для .NET разработчиков все WinRT типы выглядят как типы производные отSystem.Object и соответственно наследуют такие способы как EqualsGetHashCode и т.д. Это становится допустимым вследствие тому, что CLR осуществляет маршалинг объектов во время выполнения для реформирования типов между WinRT и .NET представлениями.

Конструкции

Конструкции WinRT, в различие от важных типов CLR, могут содержать только открытые поля одного из базовых типов либо же являться иной конструкцией WinRT. Таким образом, дальнейший код выдаст ошибку на этапе компиляции:

public struct MyStruct
{
    // 'MyStruct' contains non-public field 'MyStruct.i'.
    // Windows Runtime structures can contain only public fields.
    private Int32 i;

    //Windows Runtime structures can contain only fields.
    public MyStruct(Int32 i)
    {
        this.i = i;
    }

    //Windows Runtime structures can contain only fields.
    public void MyFunc() { }
}

К тому же, конструкции WinRT не могут определять конструкторы либо содержать вспомогательные способы. Впрочем, некоторые конструкции CLR, для комфорта, проецирует на свои личные, тем самым предоставляя разработчикам вспомогательные способы и конструкторы. К таким относятся, скажем, конструкцияWindows.Foundation.PointWindows.Foundation.Size и Windows.Foundation.Rect.

Строки

Тип System.String в WinRT представляется как HSTRING. Когда вы вызываете способ среды выполнения Windows, CLR преобразовывает всякую .NET Framework строку в HSTRING перед вызовом способа. Подобно, CLR преобразовывает всякие строки, возвращенные из способа среды выполнения в тип System.String. Есть еще одна специфика — система типов WinRT не разрешает строкам принимать значение null. Взамен null для передачи пустой строки следует применять String.Empty. При попытке передать null в качестве строки в WinRT функцию, CLR выдаст исключение ArgumentNullException. Верно так же вы никогда не увидите, что WinRT функция может воротить null-строку, это может быть только пустая строка.

Null-совместимые типы

В WinRT API для определения null-совместимого важного типа применяется интерфейсWindows.Foundation.IReference<T>, тот, что CLR проецирует на свой личный System.Nullable<T>. Скажем, если способ в файле WinMD имеет следующую сигнатуру:

IReference<bool> Method(IReference<int> i);

то в управляемом коде данный способ будет выглядеть дальнейшим образом:

Nullable<bool> Method(Nullable<int> i);
Делегаты

В качестве типа параметра либо возвращаемого значения делегата WinRT могут применять только WinRT-совместимые типы. Так же делегаты с всеобщей (public) областью видимости не могут быть объявлены как вложенные (на самом деле это всеобщие правила для среды выполнения Windows в целом). Когда вы передаете объект делегата компоненту Windows Runtime, данный объект упаковывается в обертку CCW, которая не уничтожается сборщиком мусора до тех пор, пока она не будет освобождена компонентом, тот, что ее использует. Увлекателен так же тот факт, что делегаты WinRT не имеют способов BeginInvoke и EndInvoke.

События

Компоненты WinRT могут определять события, применяя только типы делегатов WinRT. Существует тип делегата Windows.Foundation.EventHandler<T>, тот, что CLR проецирует на тип делегата .NET FrameworkSystem.EventHandler<TEventArgs>. Когда вы определяете член-событие:

public event EventHandler<RoutedEventArgs> MyEvent;

то при компиляции этой строки кода, компилятор трансформирует ее в следующие инструкции:

private EventRegistrationTokenTable<EventHandler<RoutedEventArgs>> MyEvent;

public EventRegistrationToken add_MyEvent(EventHandler<RoutedEventArgs> handler)
{
    return EventRegistrationTokenTable<EventHandler<RoutedEventArgs>>
                .GetOrCreateEventRegistrationTokenTable(ref MyEvent)
                .AddEventHandler(handler);
}

public void remove_MyEvent(EventRegistrationToken token)
{
    EventRegistrationTokenTable<EventHandler<RoutedEventArgs>>
                .GetOrCreateEventRegistrationTokenTable(ref MyEvent)
                .RemoveEventHandler(token);
}

Как и раньше, компилятор создает закрытое поле и два способа-аксессора для регистрации и отказа от подписки на событие. Впрочем тип поля и оглавление этих способов отличается от того, к чему мы привыкли (Delegate.Combine и Delegate.Remove). В качестве типа поля применяется обобщенный классEventRegistrationTokenTable<T>, доводом типа которого является соответствующий тип делегата. Данный класс отвечает за хранения цепочки делегатов, которые представляют обработчики события. При добавлении нового обработчика, возвращается токен EventRegistrationToken, тот, что может применяться в последующем для удаления обработчика события.

public void RaiseEvent()
{
    var list = EventRegistrationTokenTable<EventHandler<RoutedEventArgs>>
                .GetOrCreateEventRegistrationTokenTable(ref MyEvent)
                .InvocationList;
    if (list != null)
        list(this, new RoutedEventArgs());
}

public void Main()
{
    var myClass = new MyClass();
    var token = myClass.add_MyEvent(Handler);
    myClass.RaiseEvent();
    myClass.remove_MyEvent(token);
    myClass.RaiseEvent();
}

private void Handler(object sender, RoutedEventArgs args)
{
    Debug.WriteLine("event handling");
}

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

Время и дата

В WinRT время и дата представляются в формате UTC конструкцией Windows.Foundation.DateTime. CLR проецирует данный тип на конструкцию System.DateTimeOffset, а не на System.DateTime. Стоит подметить,чтоDateTime не содержит информацию о часовом поясе. Следственно дата и время, возвращаемые функциями WinRT в формате UTC, CLR преобразует в локальное время. И напротив, при передаче конструкцииDateTimeOffset в WinRT функцию, дата и время преобразуются в UTC формат.

Массивы

WinRT API поддерживает только одномерные массивы. Соответственно дальнейший код вызовет ошибку времени компиляции:

// Arrays in Windows Runtime method signatures must be one dimensional.
public int[,] MyFunc()
{
    return new int[5, 5];
}

В управляемом коде массивы передаются по ссылке, при этом метаморфозы элементов массива будут видны любому коду, тот, что имеет ссылку на экземпляр этого массива. Впрочем, для WinRT это не неизменно так, потому что содержимое массива маршалируется только в направлении, которое API определяет в своей сигнатуре, применяя System.Runtime.InteropServices.InAttribute и System.Runtime.InteropServices.OutAttribute. Оба признака используются к параметрам способа либо возвращаемым значениям и определяют направление маршалинга между управляемой и неуправляемой памятью во время выполнения. В Windows Runtime параметры могут быть либо только для чтения [InAttribute], либо только для записи [OutAttribute] и не могут быть подмечены для чтения и записи единовременно [InAttribute], [OutAttribute]. Это обозначает, что содержимое массива, передаваемого способу, а также сам массив обязаны быть предуготовлены для чтения либо для записи. Так, содержимое массива, тот, что помечен признаком [InAttribute], копируется в вызываемый способ, следственно все метаморфозы, которые способ применяет к массиву, не видны вызывающему объекту. Подобно, содержимое массива, тот, что помечен признаком [OutAttribute], устанавливается вызываемым способом и копируется в дерзкий объект, следственно вызываемый способ не должен делать каких-либо предположений о содержимом начального массива.

Коллекции

При передачи коллекции CLR упаковывает объект коллекции в обертку CCW и передает ссылку на нее в WinRT API. При этом вызовы через обертку пересекают рубеж взаимодействия, что негативно сказывается на продуктивности. Впрочем, в различие от массивов, допустимо выполнение операций без копирования элементов.

Завершение

Подводя результаты, подмечу, что вследствие изменениям в CLR, разработчики управляемого кода могут легко приспособиться к новому Windows Runtime API, применяя знакомые им спецтехнологии. В данной статье я описал вдалеке не все подробности взаимодействия WinRT и CLR. Впрочем, это может послужить основой для последующего постижения и больше велико понимания Windows Runtime.

Источник: programmingmaster.ru
Оставить комментарий
Форум phpBB, русская поддержка форума phpBB
Рейтинг@Mail.ru 2008 - 2017 © BB3x.ru - русская поддержка форума phpBB