![]() |
Исполняющая среда динамических языковDate: 2015-10-07; view: 374. Хотя с технической точки зрения Visual Basic в своей основе является статическим языком, в нем всегда были очень мощные динамические средства, например позднее связывание (late binding). Visual Studio 2010 поставляется с новой платформой под названием Dynamic Language Runtime (DLR), которая упрощает создание динамических языков и взаимодействие между ними. Visual Basic 2010 полностью поддерживает DLR, позволяя использовать библиотеки и инфраструктуры, написанные на таких языках, как IronPython и IronRuby. Самое интересное, что эта поддержка не потребовала никаких изменений в синтаксисе (фактически в компиляторе не было модифицировано ни одной строки кода). Разработчики могут по-прежнему, как и в предыдущих версиях Visual Basic, определять операции с поздним связыванием. Изменения внесены в исполняющую среду Visual Basic Runtime (Microsoft.VisualBasic.dll), которая теперь распознает интерфейс IDynamicMetaObjectProvider, предоставляемый DLR. Если объект реализует этот интерфейс, Visual Basic Runtime сконструирует DLR CallSite и позволит этому объекту и предоставляющему его языку object ввести в операцию собственную семантику. Например, стандартные библиотеки Python (Python Standard Libraries) содержат файл random.py с методом shuffle, который можно использовать для случайного переупорядочения элементов в массиве. Вызвать его несложно: Dim python As ScriptRuntime = Python.CreateRuntime() Dim random As Object = python.UseFile("random.py")
Dim items = {1, 2, 3, 4, 5, 6, 7} random.shuffle(items) В период выполнения Visual Basic обнаруживает, что объект реализует IDynamicMetaObjectProvider, и передает управление DLR, которая взаимодействует с Python и выполняет метод (передавая массив, определенный в Visual Basic как аргумент метода). Это пример вызова API с поддержкой DLR, но разработчики могут создавать свои API, использующие DLR. Самое главное при этом — реализовать интерфейс IDynamicMetaObjectProvider, и тогда компиляторы Visual Basic и C# увидят, что объект имеет особую динамическую семантику. Вместо реализации интерфейса вручную проще наследовать от класса System.Dynamic.DynamicObject (который уже реализует этот интерфейс) и переопределить пару методов. На рис. 3 показан полный пример создания собственного динамического объекта и его вызова с использованием обычного для Visual Basic механизма позднего связывания. Рис.3 Создание собственного динамического объекта и его вызов из Visual Basic через механизм позднего связывания Imports System.Dynamic Module Module1 Sub Main() Dim p As Object = New PropertyBag p.One = 1 p.Two = 2 p.Three = 3 Console.WriteLine(p.One) Console.WriteLine(p.Two) Console.WriteLine(p.Three) End Sub Class PropertyBag : Inherits DynamicObject Private values As New Dictionary(Of String, Integer) Public Overrides Function TrySetMember( ByVal binder As SetMemberBinder, ByVal value As Object) As Boolean values(binder.Name) = value Return True End Function Public Overrides Function TryGetMember( ByVal binder As GetMemberBinder, ByRef result As Object) As Boolean Return values.TryGetValue(binder.Name, result) End Function End Class End Module Обобщенная вариантность Эта функциональность, название которой поначалу кажется весьма заумным (с ее терминами «ковариантность» и «контравариантность»), на самом деле довольно проста. Если у вас есть объект типа IEnumerable(Of Apple) и вы хотите присвоить его IEnumerable(Of Fruit), то эта операция должна быть допустимой, так как каждый объект Apple (яблоко) наследует от Fruit (фрукт). Увы, до Visual Basic 2010 обобщенная вариантность не поддерживалась компилятором, хотя общеязыковая исполняющая среда (Common Language Runtime, CLR) полностью поддерживала такую возможность. Рис.4 Пример обобщенной вариантности Option Strict On Public Class Form1 Sub Form1_Load() Handles MyBase.Load Dim buttons As New List(Of Button) From { New Button With { .Name = "btnOk", .Enabled = True }, New Button With { .Name = "btnCancel", .Enabled = False } }
Dim enabledOnly = FilterEnabledOnly(buttons) End Sub Function FilterEnabledOnly( ByVal controls As IEnumerable(Of Control) ) As IEnumerable(Of Control) Return From c In controls Where c.Enabled = True End Function End Class Самое большое преимущество обобщенной вариантности — об этой функциональности не нужно беспокоиться самому:если она выполняет свою работу, вы никогда этого не заметите. Ситуации, в которых раньше возникали ошибки компиляции или требовался вызов .Cast(Of T), не должны создавать проблем в Visual Basic 2010.
|