Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Динамические объекты предоставляют такие элементы, как свойства и методы во время выполнения, а не во время компиляции. Динамические объекты позволяют создавать объекты для работы со структурами, которые не соответствуют статичным типам или формату. Например, динамический объект можно использовать для ссылки на объектную модель HTML-документа (DOM), которая может содержать любое сочетание допустимых элементов разметки HTML и атрибутов. Так как каждый HTML-документ является уникальным, элементы для определенного HTML-документа определяются во время выполнения. Распространенный метод ссылки на атрибут html-элемента — передать имя атрибута GetProperty
методу элемента. Чтобы ссылаться на id
атрибут HTML-элемента <div id="Div1">
, сначала получите ссылку на элемент <div>
, а затем используйте divElement.GetProperty("id")
. При использовании динамического объекта можно ссылаться на id
атрибут как divElement.id
.
Динамические объекты также обеспечивают удобный доступ к динамическим языкам, таким как IronPython и IronRuby. Динамический объект можно использовать для ссылки на динамический скрипт, интерпретируемый во время выполнения.
Вы обращаетесь к динамическому объекту, используя позднее связывание. Тип объекта с поздней привязкой указывается как dynamic
. Дополнительные сведения см. в типе dynamic.
Вы можете создавать пользовательские динамические объекты, используя классы в пространстве имен System.Dynamic. Например, можно создать ExpandoObject и указать члены этого объекта во время выполнения. Вы также можете создать собственный тип, наследующий DynamicObject класс. Затем можно переопределить члены DynamicObject класса, чтобы обеспечить динамическую функциональность во время выполнения.
В этой статье содержатся два независимых пошагового руководства.
- Создайте пользовательский объект, динамически предоставляющий содержимое текстового файла в качестве свойств объекта.
- Создайте проект, использующий библиотеку
IronPython
.
Предпосылки
- Visual Studio 2022 версии 17.3 или более поздней версии с установленной рабочей нагрузкой разработка приложений для настольных ПК .NET. Пакет SDK для .NET 7 включается при выборе этой рабочей нагрузки.
Замечание
На компьютере могут отображаться различные имена или расположения для некоторых элементов пользовательского интерфейса Visual Studio в следующих инструкциях. Выпуск Visual Studio, который у вас есть, и параметры, которые вы используете, определяют эти элементы. Дополнительные сведения см. в разделе Персонализация интегрированной среды разработки.
- Во втором пошаговом руководстве установите IronPython для .NET. Перейдите на страницу скачивания , чтобы получить последнюю версию.
Создание настраиваемого динамического объекта
В первом пошаговом руководстве определяется пользовательский динамический объект, который выполняет поиск содержимого текстового файла. Динамическое свойство определяет текст, который нужно искать. Например, если вызывающий код указывает dynamicFile.Sample
, динамический класс возвращает обобщенный список строк, содержащий все строки из файла, которые начинаются с "Sample". Поиск не учитывает регистр. Динамический класс также поддерживает два необязательных аргумента. Первый аргумент — это значение перечисления параметра поиска, указывающее, что динамический класс должен искать совпадения в начале строки, конце строки или в любом месте строки. Второй аргумент указывает, что динамический класс должен обрезать начальные и конечные пробелы от каждой строки перед поиском. Например, если вызывающий код задает dynamicFile.Sample(StringSearchOption.Contains)
, динамический класс ищет "Sample" в любом месте строки. Если вызывающий код указывает dynamicFile.Sample(StringSearchOption.StartsWith, false)
, динамический класс выполняет поиск "Sample" в начале каждой строки и не удаляет начальные и конечные пробелы. Поведение динамического класса по умолчанию заключается в поиске совпадения в начале каждой строки и удалении начальных и конечных пространств.
Создание настраиваемого динамического класса
Запустите Visual Studio. Выберите Создать новый проект. В диалоговом окне "Создание проекта " выберите C#, выберите консольное приложение и нажмите кнопку "Далее". В диалоговом окне "Настройка нового проекта " введите DynamicSample
имя проекта и нажмите кнопку "Далее". В диалоговом окне "Дополнительные сведения" выберите .NET 7.0 (Current) для целевой платформы и нажмите кнопку "Создать". В обозревателе решений щелкните правой кнопкой мыши проект DynamicSample и выберите "Добавить>класс". В поле "Имя" введите ReadOnlyFile
и нажмите кнопку "Добавить". В верхней части файла ReadOnlyFile.cs или ReadOnlyFile.vb добавьте следующий код для импорта System.IO и System.Dynamic пространств имен.
using System.IO;
using System.Dynamic;
Настраиваемый динамический объект использует перечисление для определения критериев поиска. Перед оператором класса добавьте следующее определение перечисления.
public enum StringSearchOption
{
StartsWith,
Contains,
EndsWith
}
Обновите определение класса, чтобы наследовать класс DynamicObject
, как показано в примере кода ниже.
class ReadOnlyFile : DynamicObject
Добавьте следующий код в ReadOnlyFile
класс, чтобы определить частное поле для пути к файлу и конструктор для ReadOnlyFile
класса.
// Store the path to the file and the initial line count value.
private string p_filePath;
// Public constructor. Verify that file exists and store the path in
// the private variable.
public ReadOnlyFile(string filePath)
{
if (!File.Exists(filePath))
{
throw new Exception("File path does not exist.");
}
p_filePath = filePath;
}
- Добавьте следующий
GetPropertyValue
метод вReadOnlyFile
класс. МетодGetPropertyValue
принимает в качестве входных данных, критерии поиска и возвращает строки из текстового файла, соответствующего этим критериям поиска. Динамические методы,ReadOnlyFile
предоставляемые классом, вызываютGetPropertyValue
метод для получения соответствующих результатов.
public List<string> GetPropertyValue(string propertyName,
StringSearchOption StringSearchOption = StringSearchOption.StartsWith,
bool trimSpaces = true)
{
StreamReader sr = null;
List<string> results = new List<string>();
string line = "";
string testLine = "";
try
{
sr = new StreamReader(p_filePath);
while (!sr.EndOfStream)
{
line = sr.ReadLine();
// Perform a case-insensitive search by using the specified search options.
testLine = line.ToUpper();
if (trimSpaces) { testLine = testLine.Trim(); }
switch (StringSearchOption)
{
case StringSearchOption.StartsWith:
if (testLine.StartsWith(propertyName.ToUpper())) { results.Add(line); }
break;
case StringSearchOption.Contains:
if (testLine.Contains(propertyName.ToUpper())) { results.Add(line); }
break;
case StringSearchOption.EndsWith:
if (testLine.EndsWith(propertyName.ToUpper())) { results.Add(line); }
break;
}
}
}
catch
{
// Trap any exception that occurs in reading the file and return null.
results = null;
}
finally
{
if (sr != null) {sr.Close();}
}
return results;
}
Добавьте следующий код после метода GetPropertyValue
, чтобы переопределить метод TryGetMember класса DynamicObject. Метод TryGetMember вызывается при запросе члена динамического класса, и аргументы не указаны. Аргумент binder
содержит сведения о указанном элементе, а result
аргумент ссылается на результат, возвращаемый для указанного элемента. Метод TryGetMember возвращает логическое значение, возвращающее true
, если запрошенный член существует; в противном случае возвращается false
.
// Implement the TryGetMember method of the DynamicObject class for dynamic member calls.
public override bool TryGetMember(GetMemberBinder binder,
out object result)
{
result = GetPropertyValue(binder.Name);
return result == null ? false : true;
}
Добавьте следующий код после метода TryGetMember
, чтобы переопределить метод TryInvokeMember класса DynamicObject. Метод TryInvokeMember вызывается, когда член динамического класса запрашивается с аргументами. Аргумент binder
содержит сведения о указанном элементе, а result
аргумент ссылается на результат, возвращаемый для указанного элемента. Аргумент args
содержит массив аргументов, передаваемых члену. Метод TryInvokeMember возвращает логическое значение, возвращающее true
, если запрошенный член существует; в противном случае возвращается false
.
Пользовательская версия метода ожидает, что первый аргумент будет значением из перечисления TryInvokeMember
, который вы определили на предыдущем шаге. Метод TryInvokeMember
ожидает, что второй аргумент будет булевым значением. Если один или оба аргумента являются допустимыми значениями, они передаются методу GetPropertyValue
для получения результатов.
// Implement the TryInvokeMember method of the DynamicObject class for
// dynamic member calls that have arguments.
public override bool TryInvokeMember(InvokeMemberBinder binder,
object[] args,
out object result)
{
StringSearchOption StringSearchOption = StringSearchOption.StartsWith;
bool trimSpaces = true;
try
{
if (args.Length > 0) { StringSearchOption = (StringSearchOption)args[0]; }
}
catch
{
throw new ArgumentException("StringSearchOption argument must be a StringSearchOption enum value.");
}
try
{
if (args.Length > 1) { trimSpaces = (bool)args[1]; }
}
catch
{
throw new ArgumentException("trimSpaces argument must be a Boolean value.");
}
result = GetPropertyValue(binder.Name, StringSearchOption, trimSpaces);
return result == null ? false : true;
}
Сохраните и закройте файл.
Создание примера текстового файла
В обозревателе решений щелкните правой кнопкой мыши проект DynamicSample и выберите "Добавить>новый элемент". В области "Установленные шаблоны " выберите "Общие" и выберите шаблон "Текстовый файл ". Оставьте имя по умолчанию TextFile1.txt в поле "Имя ", а затем нажмите кнопку "Добавить". Скопируйте следующий текст в файл TextFile1.txt .
List of customers and suppliers
Supplier: Lucerne Publishing (https://www.lucernepublishing.com/)
Customer: Preston, Chris
Customer: Hines, Patrick
Customer: Cameron, Maria
Supplier: Graphic Design Institute (https://www.graphicdesigninstitute.com/)
Supplier: Fabrikam, Inc. (https://www.fabrikam.com/)
Customer: Seubert, Roxanne
Supplier: Proseware, Inc. (http://www.proseware.com/)
Customer: Adolphi, Stephan
Customer: Koch, Paul
Сохраните и закройте файл.
Создание примера приложения, использующего пользовательский динамический объект
В обозревателе решений дважды щелкните файл Program.cs . Добавьте следующий код в Main
процедуру для создания экземпляра ReadOnlyFile
класса для файла TextFile1.txt . Код использует позднюю привязку для вызова динамических элементов и получения строк текста, содержащих строку Customer.
dynamic rFile = new ReadOnlyFile(@"..\..\..\TextFile1.txt");
foreach (string line in rFile.Customer)
{
Console.WriteLine(line);
}
Console.WriteLine("----------------------------");
foreach (string line in rFile.Customer(StringSearchOption.Contains, true))
{
Console.WriteLine(line);
}
Сохраните файл и нажмите клавиши CTRL+F5 для сборки и запуска приложения.
Вызов динамической языковой библиотеки
В следующем пошаговом руководстве создается проект, который обращается к библиотеке, написанной на динамическом языке IronPython.
Создание настраиваемого динамического класса
В Visual Studio выберите файл>нового>проекта. В диалоговом окне "Создание проекта " выберите C#, выберите консольное приложение и нажмите кнопку "Далее". В диалоговом окне "Настройка нового проекта " введите DynamicIronPythonSample
имя проекта и нажмите кнопку "Далее". В диалоговом окне "Дополнительные сведения" выберите .NET 7.0 (Current) для целевой платформы и нажмите кнопку "Создать". Установите пакет NuGet IronPython . Измените файл Program.cs . В верхней части файла добавьте следующий код, чтобы импортировать пространства имен Microsoft.Scripting.Hosting
и IronPython.Hosting
из библиотек IronPython, а также пространство имен System.Linq
.
using System.Linq;
using Microsoft.Scripting.Hosting;
using IronPython.Hosting;
В методе Main добавьте следующий код, чтобы создать новый Microsoft.Scripting.Hosting.ScriptRuntime
объект для размещения библиотек IronPython. Объект ScriptRuntime
загружает модуль библиотеки IronPython random.py.
// Set the current directory to the IronPython libraries.
System.IO.Directory.SetCurrentDirectory(
Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles) +
@"\IronPython 2.7\Lib");
// Create an instance of the random.py IronPython library.
Console.WriteLine("Loading random.py");
ScriptRuntime py = Python.CreateRuntime();
dynamic random = py.UseFile("random.py");
Console.WriteLine("random.py loaded.");
После загрузки модуля random.py добавьте следующий код, чтобы создать массив целых чисел. Массив передается методу shuffle
модуля random.py, который случайно сортирует значения в массиве.
// Initialize an enumerable set of integers.
int[] items = Enumerable.Range(1, 7).ToArray();
// Randomly shuffle the array of integers by using IronPython.
for (int i = 0; i < 5; i++)
{
random.shuffle(items);
foreach (int item in items)
{
Console.WriteLine(item);
}
Console.WriteLine("-------------------");
}
Сохраните файл и нажмите клавиши CTRL+F5 для сборки и запуска приложения.