Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 82 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
82
Dung lượng
458,53 KB
Nội dung
624 Chapter 13 Interoperating with COM The following code sample demonstrates how to use the MarshalAs attribute to control the marshaling of a property: ' VB Class SimpleClass Public txt As String End Class // C# class SimpleClass { [MarshalAs(UnmanagedType.LPWStr)] public String txt; } You need to configure marshaling manually only when the COM caller requires a data format other than what the default marshaling would use Lab: Expose a NET Framework Class to COM In this lab, you will prepare a NET Framework class to be accessed from COM applications Exercise: Prepare and Register a NET Framework Class In this exercise, you will update a NET Framework class so that it follows guidelines for being accessed from a COM application Then you register the library with COM Navigate to the \\Chapter13\Lesson2\Exercise1\Partial folder and open either the C# version or the Visual Basic NET version of the solution file Add the System.Runtime.InteropServices namespace to your code file Types, methods, properties, fields, and events must be public Although the _value property shouldn’t be accessed directly, you still must change it to public To prevent COM applications from accessing it, use the ComVisible attribute to hide it ' VB _ Public _value As Integer = // C# [ComVisible(false)] public int _value = 0; Build the assembly Note the folder that the assembly is stored in Run the Visual Studio Command Prompt with administrative credentials In Windows Vista, you need to right-click the prompt, click Run As Administrator, and then respond to the User Account Control (UAC) prompt Lesson 2: Using NET Types from COM Applications 625 Use Tlbexp.exe to create a type library from the assembly by running the following command, replacing appropriately: Tlbexp "\MathLibrary.dll" The type library is ready to use Now, register the assembly using Regasm Run the following command: Regasm /tlb "\MathLibrary.dll" Now, your NET Framework class is ready to be accessed from a COM application Lesson Summary When creating a NET type to be used by COM applications, mark all types, methods, properties, fields, and events as public, and use ComVisibleAttribute to hide members Provide only a default constructor Avoid using abstract types and static methods Include HRESULT error codes in custom exception classes and provide GUIDs for types that require them Use InAttribute and OutAttribute to allow callers to see changes made to parameters by the callee Use Tlbexp.exe to export an assembly to a type library You can register an assembly during the build process using Visual Studio Alternatively, you can use Regasm.exe to register an assembly manually Set the Exception.HResult property to define an HRESULT value for a custom exception class Use the MarshalAs attribute to override the default marshaling behavior This is required only when the caller requires the data in a format other than the format that marshaling provides by default Lesson Review You can use the following questions to test your knowledge of the information in Lesson 2, “Using NET Types from COM Applications.” The questions are also available on the companion CD if you prefer to review them in electronic form NOTE Answers Answers to these questions and explanations of why each answer choice is right or wrong are located in the “Answers” section at the end of the book 626 Chapter 13 Interoperating with COM You are creating a class that will be accessed by COM applications Which of the following should you do? (Choose all that apply.) A Make the class abstract B Create all methods as public C Create all methods as static D Provide a default constructor You are creating a class that will be accessed from COM applications You want changes made to parameters to be available to the calling application Which of the following attributes should you apply to the parameters? (Choose all that apply.) A ClassInterfaceAttribute B InAttribute C OutAttribute D AutomationProxyAttribute You are creating a NET Framework application that needs to call methods located in a COM object You want to create a NET Framework assembly using the COM object so that you can reference it more easily in your project Which tool should you use? A Tlbimp.exe B Tlbexp.exe C Regasm.exe D Regedit.exe Chapter 13 Review 627 Chapter Review To practice and reinforce the skills you learned in this chapter further, you can perform the following tasks: Review the chapter summary Review the list of key terms introduced in this chapter Complete the case scenarios These scenarios set up real-world situations involving the topics of this chapter and ask you to create a solution Complete the suggested practices Take a practice test Chapter Summary You can access a COM library by adding a reference in Visual Studio, by using the Tlbimp.exe command-line tool, or by creating prototype methods using the DllImport attribute Use the Marshal.GetLastWin32Error static method to retrieve the last Win32 error code If a function requires a nonstandard structure layout, specify the layout using the StructLayout attribute To implement a callback function, create a method to handle the callback, a delegate, and a prototype Create a wrapper class to provide a managed interface for unmanaged objects For NET types to be accessible to COM applications, they must follow specific guidelines, including having public members, providing a default constructor, and avoiding static methods Use Tlbexp.exe to export an assembly to a type library You can register an assembly during the build process using Visual Studio or with the Regasm.exe tool Set the Exception.HResult property to define an HRESULT value for a custom exception class Use the MarshalAs attribute to override the default marshaling behavior Key Terms Do you know what these key terms mean? You can check your answers by looking up the terms in the glossary at the end of the book Component Object Model (COM) Marshaling Type library 628 Chapter 13 Review Case Scenarios In the following case scenarios, you apply what you’ve learned about how to interoperate with COM You can find answers to these questions in the “Answers” section at the end of this book Case Scenario 1: Creating a NET Framework User Interface with COM Libraries You are an application developer for Alpine Ski House You and your team are updating the application that employees use to sell lift tickets, book rooms, and rent equipment The previous version of the application was written in C++ using Win32 It uses several COM libraries for application logic, such as communicating with the back-end database As you begin to migrate the application to the NET Framework, you plan to start by rewriting the user interface Once the user interface is in place, you will rewrite the application logic Therefore, you need the user interface (written using the NET Framework) to call methods in the COM libraries Questions Answer the following questions for your manager: How can you call methods in COM libraries from a NET Framework application? Several of the COM functions require you to pass structures to them How can you ensure that the structures are passed in the correct format? I’d rather have the other developers accessing a NET Framework class Can you create a managed class that simply forwards all requests to the unmanaged types? Case Scenario 2: Creating a NET Library That Can Be Accessed from COM You are an application developer working for Proseware, Inc You are in the process of updating a three-tiered application Currently, the user interface is a Win32 application The application logic is implemented in COM objects The third layer is a SQL Server database Although you plan to replace both the user interface and the application logic with the NET Framework, you plan to replace the application logic first To replace COM objects, you must allow the Win32 user interface to create instances of managed classes Although you can update the Win32 user interface to access different libraries, you want to minimize the scope of the changes Chapter 13 Review 629 Questions Answer the following questions for your manager: How can you replace the COM objects with a NET Framework library? Given that COM applications don’t support exceptions, how will you pass error information back to COM? How can you ensure that strings are passed back in the correct format? Suggested Practices To master the “Implementing Interoperability, Reflection, and Mailing Functionality in a NET Framework Application” exam objective, complete the following tasks Expose COM Components to the NET Framework and the NET Framework Components to COM For this task, you should complete at least Practices and If you have the resources and knowledge to create Win32 applications, complete Practices and as well Create a NET Framework application that accesses a COM object Handle any exceptions that might arise Practice Create a wrapper class for a COM object so that you can access it directly from managed code Practice Create a Win32 application that accesses a NET Framework class that you created for a real-world application Troubleshoot any problems that arise Practice Create a Win32 application that accesses the Math class that you created in the Lesson lab Practice Call Unmanaged DLL Functions within a NET Framework Application, and Control the Marshaling of Data in a NET Framework Application For this task, you should complete both practices Using a real-world class that you created, manually configure marshaling for all properties and methods Practice Create a custom exception class (or use a real-world exception class that you created) and define a specific HRESULT value Practice 630 Chapter 13 Review Take a Practice Test The practice tests on this book’s companion CD offer many options For example, you can test yourself on just the content covered in this chapter, or you can test yourself on all the 70-536 certification exam content You can set up the test so that it closely simulates the experience of taking a certification exam, or you can set it up in study mode so that you can look at the correct answers and explanations after you answer each question MORE INFO Practice tests For details about all the practice test options available, see the section “How to Use the Practice Tests,” in the Introduction of this book Chapter 14 Reflection Using reflection, the NET Framework gives you the ability to open, run, and even generate assemblies and the types contained within dynamically Reflection is useful anytime you need to examine or run code that isn’t available at runtime, such as when you need to load add-ons This chapter provides an overview of how to use reflection Exam objective in this chapter: Implement reflection functionality in a NET Framework application, and create metadata, Microsoft intermediate language (MSIL), and a PE file by using the System.Reflection.Emit namespace Lesson in this chapter: Lesson 1: Using Reflection 632 Before You Begin To complete the lesson in this chapter, you should be familiar with Microsoft Visual Basic or C# and be comfortable with the following tasks: Creating a Console application in Microsoft Visual Studio using Visual Basic or C# Adding namespaces and system class library references to a project 631 632 Chapter 14 Reflection Lesson 1: Using Reflection In most development scenarios, you have access to all the assemblies and code that your application requires during the development process However, some applications require extensibility that can be achieved only by writing code that can dynamically add features contained in external assemblies Depending on your requirements, you might even need to generate an assembly dynamically This lesson provides an overview of reflection and describes how to create instances of types and call methods in a dynamically loaded assembly, how to load assemblies, how to define and examine assembly attributes, and how to generate assemblies and types dynamically After this lesson, you will be able to: Describe how reflection works Load assemblies dynamically Create instances of types and call methods in a dynamically loaded assembly Edit and read assembly attributes Generate assemblies, types, constructors, and methods dynamically Estimated lesson time: 30 minutes Reflection Overview Most of the time, you have direct access to types during development However, there are times when you might want to load an assembly, and the types and methods contained within, dynamically at runtime For example, an application that supports plug-ins should be written to run a plug-in dynamically even though the plug-in is not accessible when the application is being developed Reflection allows you to load assemblies at runtime, dynamically create an instance of a type, and bind the type to an existing object Then you can invoke the type’s methods and access its properties How to Load Assemblies You can load an assembly at runtime Once you load the assembly, you can examine its attributes and, depending on the method you used to load it, create instances of types and run methods The methods you can use to load an assembly are the following: Assembly.Load Loads an assembly by name, usually from the Global Assembly Cache (GAC) Assembly.LoadFile Loads an assembly by specifying the filename Lesson 1: Using Reflection Assembly.LoadFrom 633 Loads an assembly given its filename or path Loads an assembly, usually from the GAC, in a reflection-only context (described next) Assembly.ReflectionOnlyLoad Assembly.ReflectionOnlyLoadFrom Loads an assembly, in a reflection-only con- text, by specifying the filename Loading an assembly in a reflection-only context allows you to examine the assembly but not create instances of types or run methods Therefore, it’s useful only when you need to examine an assembly or the code contained within it Often, developers use the reflection-only context to examine assemblies compiled for other platforms or for other versions of the NET Framework To load an assembly in a reflection-only context, use the Assembly.ReflectionOnlyLoad or Assembly.ReflectionOnlyLoadFrom method Although you can’t create objects, you can examine the assembly’s attributes, as described later in this lesson How to Create Instances and Call Methods You can use reflection to create an instance of a type that isn’t available until runtime by creating an instance of the Type class Although you can simply specify an existing type, typically you would create the Type by calling Assembly.GetType and specifying the name of the type to load from the assembly Once you create an instance of Type, you can access the members of the type Call Type.GetMethod to create an instance of MethodInfo GetMethod requires you to specify the method name (as a string) and the parameters required by the method (as a Type array) Once you create an instance of MethodInfo, you can call the method using MethodInfo.Invoke The first parameter of Invoke is the object instance that contains the method The second parameter of Invoke is an object array representing the parameters required by the method Invoke always returns an Object instance, which you can cast to the type returned by the method you called The following code sample demonstrates how to create a StringBuilder instance and call StringBuilder.Append using reflection In the real world, you wouldn’t create a Type instance for a class built into the NET Framework Instead, you would load a type from an external assembly: ' VB ' Create a Type instance ' Typically, this would be done by loading an external assembly, ' and then calling Assembly.GetType() Dim t As Type = GetType(StringBuilder) Lesson 1: Formatting Data for Globalization 691 Consider the following code sample: ' VB Public Sub Main() Dim words As String() = New String() {"Apple", "Ỉble"} Thread.CurrentThread.CurrentCulture = New CultureInfo("en-US") SortWords(words) Thread.CurrentThread.CurrentCulture = New CultureInfo("da-DK") SortWords(words) End Sub Private Sub SortWords(ByVal words As String()) Console.WriteLine(Thread.CurrentThread.CurrentCulture) Array.Sort(words) For Each s As String In words Console.WriteLine(s) Next End Sub // C# public static void Main() { string[] words = new string[] { "Apple", "Ỉble" }; Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US"); SortWords(words); Thread.CurrentThread.CurrentCulture = new CultureInfo("da-DK"); SortWords(words); } private static void SortWords(string[] words) { Console.WriteLine(Thread.CurrentThread.CurrentCulture); Array.Sort(words); foreach (string s in words) { Console.WriteLine(s); } } This Console application produces the following output, demonstrating that changing the culture also changes the sort order: en-US Ỉble Apple da-DK Apple Ỉble 692 Chapter 16 Globalization Some cultures support more than one sort order For example, the zh-CN culture (Chinese in China) supports sorting either by pronunciation (the default) or by stroke count (the alternate) To specify the alternate sort order, create a new CultureInfo object (as described in the section “How to Build a Custom Culture Class,” later in this lesson) using the locale identifier (LCID) for the alternate sort order Table 16-1 lists the cultures that support multiple sort orders and the number that identifies each sort order Table 16-1 Cultures That Support Multiple Sort Orders Culture Name Culture Default Sort Name and LCID Alternate Sort Name and LCID es-ES Spanish (Spain) International: 0x00000C0A Traditional: 0x0000040A zh-TW Chinese (Taiwan) Stroke Count: 0x00000404 Bopomofo: 0x00030404 zh-CN Chinese (China) Pronunciation: 0x00000804 Stroke Count: 0x00020804 zh-HK Chinese (Hong Kong SAR) Stroke Count: 0x00000c04 Stroke Count: 0x00020c04 zh-SG Chinese (Singapore) Pronunciation: 0x00001004 Stroke Count: 0x00021004 zh-MO Chinese (Macao SAR) Pronunciation: 0x00001404 Stroke Count: 0x00021404 ja-JP Japanese (Japan) Default: 0x00000411 Unicode: 0x00010411 ko-KR Korean (Korea) Default: 0x00000412 Korean Xwansung— Unicode: 0x00010412 de-DE German (Germany) Dictionary: 0x00000407 Phone Book Sort: 0x00010407 hu-HU Hungarian (Hungary) Default: 0x0000040e Technical Sort: 0x0001040e ka-GE Georgian (Georgia) Traditional: 0x00000437 Modern Sort: 0x00010437 Lesson 1: Formatting Data for Globalization 693 The commonly used String.IndexOf method can return different results depending on the culture For example, in the en-US culture, Ỉ matches AE, and vice versa In the da-DK culture, Ỉ is considered a distinct letter and matches only Ỉ Consider the following code sample, which identifies the index of AE and Ỉ in two different strings: ' VB Public Sub Main() Dim words As String() = New String() {"AEble", "Ỉble"} Thread.CurrentThread.CurrentCulture = New CultureInfo("en-US") FindAE(words) Thread.CurrentThread.CurrentCulture = New CultureInfo("da-DK") FindAE(words) Console.ReadKey() End Sub Private Sub FindAE(ByVal words As String()) Console.WriteLine(Thread.CurrentThread.CurrentCulture.ToString() + ":") Array.Sort(words) For Each s As String In words Console.WriteLine(" AE in {0}: {1}", s, s.IndexOf("AE")) Console.WriteLine(" Ỉ in {0}: {1}", s, s.IndexOf("Ỉ")) Next Console.WriteLine() End Sub // C# public static void Main() { string[] words = new string[] { "AEble", "Ỉble" }; Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US"); FindAE(words); Thread.CurrentThread.CurrentCulture = new CultureInfo("da-DK"); FindAE(words); } private static void FindAE(string[] words) { Console.WriteLine(Thread.CurrentThread.CurrentCulture + ":"); Array.Sort(words); foreach (string s in words) { Console.WriteLine(" AE in {0}: {1}", s, s.IndexOf("AE")); Console.WriteLine(" Ỉ in {0}: {1}", s, s.IndexOf("Ỉ")); } Console.WriteLine(); } 694 Chapter 16 Globalization String.IndexOf returns if the value matches the first position of the string and –1 if the value cannot be found in the string The previous code sample produces these results, demonstrating the differences between the en-US and da-DK cultures: en-US: AE in Ỉble: Ỉ in Ỉble: AE in AEble: Ỉ in AEble: da-DK: AE in AEble: Ỉ in AEble: -1 AE in Ỉble: -1 Æ in Æble: Although you should be aware of possible sorting and comparison differences, typically, the differences not require specific programming techniques If, however, you plan to exchange data between computers with different cultures, you might need to specify culture-insensitive comparisons, as described in the next section Performing Culture-Insensitive Comparisons Culture-specific sorting is important when displaying information to the user However, it can cause very confusing inconsistencies when applied to internal sorting For example, imagine comparing two instances of a sorted database for consistency using a computer in the United States and a computer in Denmark: If the sort order differed, the databases might appear to be inconsistent, even though they are identical To avoid such a problem, perform culture-insensitive comparisons by specifying CultureInfo.InvariantCulture as the culture or using StringComparison.InvariantCulture in overloaded string comparison methods For example, suppose that you replace the FindAE method in the previous code sample with the following code shown in bold: ' VB Private Sub FindAE(ByVal words As String()) Console.WriteLine(Thread.CurrentThread.CurrentCulture.ToString() + ":") Array.Sort(words) For Each s As String In words Console.WriteLine(" AE in {0}: {1}", s, _ s.IndexOf("AE", StringComparison.InvariantCulture)) Console.WriteLine(" Ỉ in {0}: {1}", s, _ s.IndexOf("Ỉ", StringComparison.InvariantCulture)) Next Console.WriteLine() End Sub Lesson 1: Formatting Data for Globalization 695 // C# private static void FindAE(string[] words) { Console.WriteLine(Thread.CurrentThread.CurrentCulture + ":"); Array.Sort(words); foreach (string s in words) { Console.WriteLine(" AE in {0}: {1}", s, s.IndexOf("AE", StringComparison.InvariantCulture)); Console.WriteLine(" Ỉ in {0}: {1}", s, s.IndexOf("Ỉ", StringComparison.InvariantCulture)); } Console.WriteLine(); } This code produces the following results, which are consistent regardless of the current culture: en-US: AE in Æble: Æ in Æble: AE in AEble: Æ in AEble: da-DK: AE in AEble: Æ in AEble: AE in Ỉble: Ỉ in Ỉble: Alternatively, specifying the current culture using the following line of code would cause all subsequent comparisons to be culture-insensitive, regardless of whether you specified it for each method call: ' VB Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture //C# Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture; How to Build a Custom Culture You can use the System.Globalization.CultureAndRegionInfoBuilder class to build a new culture based on an existing one by following these steps: Create an instance of CultureAndRegionInfoBuilder, specifying the name of the new culture This instantiates the CultureName property Although CultureAndRegionInfoBuilder is in the System.Globalization namespace, you must add a reference to Sysglobl on the NET tab of the Add Reference dialog box The dynamic-link library (DLL) is located in the %Windir%\Microsoft.NET\Framework\v2.0.50727 folder 696 Chapter 16 Globalization Call the CultureAndRegionInfoBuilder.LoadDataFromCultureInfo method to copy the settings from an existing CultureInfo object Call the CultureAndRegionInfoBuilder.LoadDataFromRegionInfo method Use administrative privileges to call the CultureAndRegionInfoBuilder.Register method to save the culture With the culture registered, you can create new CultureInfo instances using the name of your new culture The following code sample demonstrates this by creating a culture named en-PL, registering it, and then creating an instance of the culture To run this code sample, you need administrative privileges: ' VB ' Create a CultureAndRegionInfoBuilder object for the new culture Dim cib As CultureAndRegionInfoBuilder = _ New CultureAndRegionInfoBuilder("en-PL", CultureAndRegionModifiers.None) ' Populate the new CultureAndRegionInfoBuilder object with culture information cib.LoadDataFromCultureInfo(New CultureInfo("en-US")) ' Populate the new CultureAndRegionInfoBuilder object with region information cib.LoadDataFromRegionInfo(New RegionInfo("US")) ' Define culture-specific settings cib.CultureEnglishName = "Pig Latin" cib.CultureNativeName = "Igpay Atinlay" cib.IsMetric = True cib.ISOCurrencySymbol = "PLD" cib.RegionEnglishName = "Pig Latin Region" cib.RegionNativeName = "Igpay Atinlay Egionray" ' Register the custom culture (requires administrative privileges) cib.Register() ' Display some of the properties of the custom culture Dim ci As CultureInfo = New CultureInfo("en-PL") Console.WriteLine("Name: Console.WriteLine("EnglishName: Console.WriteLine("NativeName: Console.WriteLine("TwoLetterISOLanguageName: Console.WriteLine("ThreeLetterISOLanguageName: Console.WriteLine("ThreeLetterWindowsLanguageName: {0}", {0}", {0}", {0}", {0}", {0}", ci.Name) ci.EnglishName) ci.NativeName) ci.TwoLetterISOLanguageName) ci.ThreeLetterISOLanguageName) ci.ThreeLetterWindowsLanguageName) // C# // Create a CultureAndRegionInfoBuilder object for the new culture CultureAndRegionInfoBuilder cib = new CultureAndRegionInfoBuilder("en-PL", CultureAndRegionModifiers.None); // Populate the new CultureAndRegionInfoBuilder object with culture information cib.LoadDataFromCultureInfo(new CultureInfo("en-US")); Lesson 1: Formatting Data for Globalization 697 // Populate the new CultureAndRegionInfoBuilder object with region information cib.LoadDataFromRegionInfo(new RegionInfo("US")); // Define culture-specific settings cib.CultureEnglishName = "Pig Latin"; cib.CultureNativeName = "Igpay Atinlay"; cib.IsMetric = true; cib.ISOCurrencySymbol = "PLD"; cib.RegionEnglishName = "Pig Latin Region"; cib.RegionNativeName = "Igpay Atinlay Egionray"; // Register the custom culture (requires administrative privileges) cib.Register(); // Display some of the properties of the custom culture CultureInfo ci = new CultureInfo("en-PL"); Console.WriteLine("Name: Console.WriteLine("EnglishName: Console.WriteLine("NativeName: Console.WriteLine("TwoLetterISOLanguageName: Console.WriteLine("ThreeLetterISOLanguageName: Console.WriteLine("ThreeLetterWindowsLanguageName: {0}", {0}", {0}", {0}", {0}", {0}", ci.Name); ci.EnglishName); ci.NativeName); ci.TwoLetterISOLanguageName); ci.ThreeLetterISOLanguageName); ci.ThreeLetterWindowsLanguageName); Because you require administrative privileges to register a culture, it should be done as part of the application’s setup process Once registered, you can create an instance of CultureInfo using your culture abbreviation with standard user privileges Lab: Browse Cultures In this lab, you will create an application that allows you to browse different cultures and examine how they display data differently Exercise: Create a WPF Application That Works with Cultures In this exercise, you will create a new WPF application that allows you to select a specific culture Then the application formats data for that culture and displays it to the user In Visual Studio, create a new project named ShowCultures using the WPF Application template Add a combobox control to the form named cultureComboBox This combobox will contain a list of specific cultures available to the NET Framework Add four label controls to the form: codeLabel, nativeLabel, currencyLabel, and dateLabel These labels will display information about the currently selected culture 698 Chapter 16 Globalization In your code file, add the System.Globalization namespace Edit the Window.Loaded event handler, which you can create by double-clicking the window in the designer In the event handler, populate the cultureComboBox with a list of specific cultures, as the following code sample demonstrates: ' VB For Each ci As CultureInfo In _ CultureInfo.GetCultures(CultureTypes.SpecificCultures) cultureComboBox.Items.Add(ci) Next //C# foreach (CultureInfo ci in CultureInfo.GetCultures(CultureTypes.SpecificCultures)) { cultureComboBox.Items.Add(ci); } Next, edit the ComboBox.SelectionChanged event handler, which you can create by double-clicking the ComboBox in the designer In the event handler, populate the Label controls with information based on the currently selected culture The following code sample demonstrates this: ' VB Dim selectedCulture As CultureInfo = DirectCast(e.AddedItems(0), CultureInfo) codeLabel.Content = selectedCulture.IetfLanguageTag nativeLabel.Content = selectedCulture.NativeName Dim d As Double = 1234567.89 currencyLabel.Content = d.ToString("C", selectedCulture) dateLabel.Content = DateTime.Now.ToString(selectedCulture) //C# CultureInfo selectedCulture = (CultureInfo)e.AddedItems[0]; codeLabel.Content = selectedCulture.IetfLanguageTag; nativeLabel.Content = selectedCulture.NativeName; double d = 1234567.89; currencyLabel.Content = d.ToString("C", selectedCulture); dateLabel.Content = DateTime.Now.ToString(selectedCulture); Build and run the application Select different cultures and examine how they display currency and date values Lesson Summary You can set the user’s current culture by setting Thread.CurrentThread.CurrentCulture to an instance of CultureInfo Overloads of ToString for numbers and the DateTime class support formatting output for a specific culture Although ToString overloads will format output for Lesson 1: Formatting Data for Globalization 699 the current culture by default, you can use different formatting rules simply by providing an instance of CultureInfo as a parameter The CultureInfo.NumberFormat and CultureInfo.DateTimeFormat properties provide detailed information about how a culture formats numbers and dates Different cultures have different sorting and comparison rules To ensure consistent sorting and comparison rules, specify CultureInfo.InvariantCulture as the culture or use StringComparison.InvariantCulture in overloaded string comparison methods To create a new culture, create an instance of CultureAndRegionInfoBuilder by specifying the name of the new culture Then call the CultureAndRegionInfoBuilder.LoadDataFromCultureInfo and CultureAndRegionInfoBuilder.LoadDataFromRegionInfo methods to copy settings from an existing culture Lesson Review You can use the following questions to test your knowledge of the information in Lesson 1, “Formatting Data for Globalization.” The questions are also available on the companion CD if you prefer to review them in electronic form NOTE Answers Answers to these questions and explanations of why each answer choice is right or wrong are located in the “Answers” section at the end of the book You are deploying a worldwide application One of your offices is located in a region of China that does not have an existing culture code that exactly meets their needs Although the zh-CN culture code is very close, this region uses slightly different number formatting Which class should you use to build a custom culture that meets your requirements? A CultureInfo B CultureAndRegionBuilderInfo C RegionInfo D CompareInfo You need to compare two strings, s1 and s2, in such a way that the comparison is made in exactly the same way regardless of culture settings Which code sample does this correctly? A String.Compare(s1, s2, true) B String.Compare(s1, s2, StringComparison.InvariantCulture) 700 Chapter 16 Globalization C String.Compare(s1, s2, StringComparison.CurrentCulture) D String.Compare(s1, s2, CultureTypes.NeutralCultures) You need to display a number as currency according to the guidelines for the es-ES culture (which might not be the user’s current culture) Which class should you use? A DateTimeFormat B CurrentUICulture C CultureInfo D RegionInfo Chapter 16 Review 701 Chapter Review To practice and reinforce the skills you learned in this chapter further, you can perform the following tasks: Review the chapter summary Review the list of key terms introduced in this chapter Complete the case scenario This scenario sets up a real-world situation involving the topics of this chapter and asks you to create a solution Complete the suggested practices Take a practice test Chapter Summary You can set the user’s current culture by setting Thread.CurrentThread.CurrentCulture to an instance of CultureInfo You can also use CultureInfo objects with the ToString method for numbers and for the DateTime class to format output for a specific culture The CultureInfo.NumberFormat and CultureInfo.DateTimeFormat properties provide detailed information about how a culture formats numbers and dates To avoid inconsistencies when sorting or comparing strings on computers with different cultures, specify CultureInfo.InvariantCulture as the culture or use StringComparison.InvariantCulture in overloaded string comparison methods To create a new culture, create an instance of CultureAndRegionInfoBuilder by specifying the name of the new culture Then call the CultureAndRegionInfoBuilder.LoadDataFromCultureInfo and CultureAndRegionInfoBuilder.LoadDataFromRegionInfo methods to copy settings from an existing culture Key Terms Do you know what these key terms mean? You can check your answers by looking up the terms in the glossary at the end of the book Culture Globalization Localization 702 Chapter 16 Review Case Scenario In the following case scenario, you apply what you’ve learned about how to implement and apply globalization technologies You can find answers to these questions in the “Answers” section at the end of this book Case Scenario: Supporting a New Culture You are an application developer for Contoso, Inc Recently, your organization opened an office in a small town in Spain After deploying one of your internal applications, you began to receive complaints from confused users indicating that the formatting of numbers is wrong In the small town where your office is, they use commas to separate groups of numbers, and periods to separate decimals, exactly as people in the United States However, in most of Spain, periods are used to separate groups of numbers, whereas commas separate decimals Your application formats data correctly for different cultures However, no existing culture exactly meets the needs of these new users Questions Answer the following questions for your manager: How can you create a new culture for the users? Which properties of CultureInfo will you need to define to meet the requirements of the users? At Contoso, users not have administrative privileges What privileges are required to register the new culture? If users lack the necessary privileges, how can you work around that? Suggested Practices To master the “Implementing globalization, drawing, and text manipulation functionality in a NET Framework application” exam objective, complete the following tasks Format Data Based on Culture Information For this task, you should complete at least Practices and If you want a better understanding of how to create a custom culture, complete Practice as well Chapter 16 Review 703 To understand another important difference between cultures, read “Custom Case Mappings and Sorting Rules” at http://msdn.microsoft.com/ library/xk2wykcz.aspx, and then run the code sample Practice Examine applications that you have written previously for globalization problems and correct them Practice Create a custom culture and implement a custom date format Then implement methods to allow the custom date format to be parsed from a string to a DateTime instance Practice Take a Practice Test The practice tests on this book’s companion CD offer many options For example, you can test yourself on just the content covered in this chapter or you can test yourself on all the 70-536 certification exam content You can set up the test so that it closely simulates the experience of taking a certification exam or you can set it up in study mode so that you can look at the correct answers and explanations after you answer each question MORE INFO Practice tests For details about all the practice test options available, see the section “How to Use the Practice Tests,” in the Introduction of this book Answers Chapter 1: Lesson Review Answers Lesson 1 Correct Answers: A, C, and D A Correct: Decimal is a value type B Incorrect: String is a reference type, though the String type is an exception and behaves in some ways like a value type C Correct: System.Drawing.Point is a value type D Correct: Integer is a value type Correct Answer: B A Incorrect: The Visual Basic sample uses angle brackets rather than parentheses The C# sample uses parentheses rather than angle brackets B Correct: This is the proper way to declare and assign a nullable integer In C#, you could also use the following: int? i = null; C Incorrect: You must use the nullable generic to declare an integer as nullable By default, integers are not nullable D Incorrect: This is not the correct syntax for using the nullable generic Lesson Correct Answers: B and C A Incorrect: Types declared as Nullable can only be value types B Correct: Strings are reference types C Correct: Exceptions are reference types D Incorrect: Value types derive from System.Object, so not all derived types are reference types 705 ... Reflection, and Mailing Functionality in a NET Framework Application? ?? exam objective, complete the following tasks Expose COM Components to the NET Framework and the NET Framework Components to COM For... Functionality in a NET Framework Application? ?? exam objective, complete the following tasks Implement Reflection Functionality in a NET Framework Application, and Create Metadata, Microsoft Intermediate... Lesson lab Practice Call Unmanaged DLL Functions within a NET Framework Application, and Control the Marshaling of Data in a NET Framework Application For this task, you should complete both practices