演练:创建和使用动态对象
创建一个自定义对象,该对象会将文本文件的内容作为对象的属性动态公开。 创建使用 IronPython 库的项目。
系统必备
![]() |
---|
以下说明中的某些 Visual Studio 用户界面元素在计算机上出现的名称或位置可能会不同。 这些元素取决于你所使用的 Visual Studio 版本和你所使用的设置。 有关详细信息,请参阅个性化 Visual Studio IDE。 |
创建自定义动态对象
创建自定义动态类
启动 Visual Studio。 在“文件”菜单上指向“新建”,然后单击“项目”。 在“新建项目”对话框的“项目类型”窗格中,确保选中“Windows”。 在“模板”窗格中,选择“控制台应用程序”。 在“名称”框中,键入 DynamicSample,然后单击“确定”。 至此新项目创建完毕。 右击 DynamicSample 项目,指向“添加”,然后单击“类”。 在“名称”框中,键入 ReadOnlyFile,然后单击“确定”。 这将添加一个包含 ReadOnlyFile 类的新文件。 在 ReadOnlyFile.cs 或 ReadOnlyFile.vb 文件的顶部,添加要导入 System.IO 和 System.Dynamic 命名空间的以下代码。 自定义动态对象使用一个枚举来确定搜索条件。 在类语句的前面,添加以下枚举定义。 更新类语句以继承 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 方法的后面添加以下代码,重写 DynamicObject 类的 TryGetMember 方法。 当请求动态类的成员且未指定任何参数时,将调用 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 方法的后面添加以下代码,重写 DynamicObject 类的 TryInvokeMember 方法。 当使用参数请求动态类的成员时,将调用 TryInvokeMember 方法。 binder 参数包含有关被引用成员的信息,而 result 参数则引用为指定的成员返回的结果。 args 参数包含一个传递给成员的参数的数组。 TryInvokeMember 方法会返回一个布尔值,如果请求的成员存在,则返回的布尔值为 true,否则返回的布尔值为 false。 TryInvokeMember 方法的自定义版本期望第一个参数为您在上一步骤中定义的 StringSearchOption 枚举中的值。 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 (http://www.lucernepublishing.com/) Customer: Preston, Chris Customer: Hines, Patrick Customer: Cameron, Maria Supplier: Graphic Design Institute (http://www.graphicdesigninstitute.com/) Supplier: Fabrikam, Inc. (http://www.fabrikam.com/) Customer: Seubert, Roxanne Supplier: Proseware, Inc. (http://www.proseware.com/) Customer: Adolphi, Stephan Customer: Koch, Paul
保存并关闭文件。 创建一个使用自定义动态对象的示例应用程序 在“解决方案资源管理器”中,双击 Module1.vb 文件(如果使用的是 Visual Basic)或 Program.cs 文件(如果使用的是 Visual C#)。 将以下代码添加到 Main 过程,为 TextFile1.txt 文件创建一个 ReadOnlyFile 类的实例。 此代码将使用后期绑定来调用动态成员,并检索包含字符串“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 编写的库。 创建此项目之前,必须安装 IronPython 2.6.1 for .NET 4.0。 可以从 CodePlex 下载 IronPython 2.6.1 for .NET 4.0。 创建自定义动态类 在 Visual Studio 中的“文件”菜单上,指向“新建”,然后单击“项目”。 在“新建项目”对话框的“项目类型”窗格中,确保选中“Windows”。 在“模板”窗格中,选择“控制台应用程序”。 在“名称”框中键入 DynamicIronPythonSample,然后单击“确定”。 至此新项目创建完毕。 如果使用的是 Visual Basic,请右击 DynamicIronPythonSample 项目,然后单击“属性”。 单击“引用”选项卡。 单击“添加”按钮。 如果使用的是 Visual C#,请在“解决方案资源管理器”中,右击“引用”文件夹,然后单击“添加引用”。 在“浏览”选项卡上,浏览到安装 IronPython 库的文件夹。 例如,C:\Program Files\IronPython 2.6 for .NET 4.0。 选择“IronPython.dll”、“IronPython.Modules.dll”、“Microsoft.Scripting.dll”和“Microsoft.Dynamic.dll”库。 单击“确定”。 如果使用的是 Visual Basic,请编辑 Module1.vb 文件。 如果使用的是 Visual C#,请编辑 Program.cs 文件。 在文件的顶部,添加下面的代码以从 IronPython 库导入 Microsoft.Scripting.Hosting 和 IronPython.Hosting 命名空间。 在 Main 方法中,添加下面的代码以创建用于托管 IronPython 库的新 Microsoft.Scripting.Hosting.ScriptRuntime 对象。 ScriptRuntime 对象加载 IronPython 库模块 random.py。 // Set the current directory to the IronPython libraries. System.IO.Directory.SetCurrentDirectory( Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles) + @"\IronPython 2.6 for .NET 4.0\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 模块的代码之后,添加下面的代码以创建一个整数数组。 数组传递给 random.py 模块的 shuffle 方法,该方法对数组中的值进行随机排序。 // 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 生成并运行应用程序。