diff --git a/snippets/csharp/System.Resources/MissingManifestResourceException/Overview/Project.csproj b/snippets/csharp/System.Resources/MissingManifestResourceException/Overview/Project.csproj new file mode 100644 index 00000000000..874c98f3477 --- /dev/null +++ b/snippets/csharp/System.Resources/MissingManifestResourceException/Overview/Project.csproj @@ -0,0 +1,8 @@ + + + + Library + net10.0 + + + diff --git a/snippets/csharp/System.Resources/MissingManifestResourceException/Overview/showdate.cs b/snippets/csharp/System.Resources/MissingManifestResourceException/Overview/showdate.cs new file mode 100644 index 00000000000..786696ddac0 --- /dev/null +++ b/snippets/csharp/System.Resources/MissingManifestResourceException/Overview/showdate.cs @@ -0,0 +1,42 @@ +// +using System; +using System.Globalization; +using System.Resources; +using System.Threading; + +[assembly: NeutralResourcesLanguage("en")] + +public class ShowDateEx +{ + public static void Main() + { + string[] cultureNames = { "en-US", "fr-FR", "ru-RU", "sv-SE" }; + ResourceManager rm = new ResourceManager("DateStrings", + typeof(Example).Assembly); + + foreach (var cultureName in cultureNames) + { + CultureInfo culture = CultureInfo.CreateSpecificCulture(cultureName); + Thread.CurrentThread.CurrentCulture = culture; + Thread.CurrentThread.CurrentUICulture = culture; + + Console.WriteLine($"Current UI Culture: {CultureInfo.CurrentUICulture.Name}"); + string dateString = rm.GetString("DateStart"); + Console.WriteLine($"{dateString} {DateTime.Now:M}.\n"); + } + } +} + +// The example displays output similar to the following: +// Current UI Culture: en-US +// Today is February 03. +// +// Current UI Culture: fr-FR +// Aujourd'hui, c'est le 3 février +// +// Current UI Culture: ru-RU +// Сегодня февраля 03. +// +// Current UI Culture: sv-SE +// Today is den 3 februari. +// diff --git a/snippets/csharp/System.Resources/MissingManifestResourceException/Overview/showdate1.cs b/snippets/csharp/System.Resources/MissingManifestResourceException/Overview/showdate1.cs new file mode 100644 index 00000000000..c73d303e636 --- /dev/null +++ b/snippets/csharp/System.Resources/MissingManifestResourceException/Overview/showdate1.cs @@ -0,0 +1,39 @@ +// +using System; +using System.Globalization; +using System.Resources; +using System.Threading; + +public class ShowTimeExample +{ + public static void Main() + { + string[] cultureNames = [ "en-US", "fr-FR", "ru-RU", "sv-SE" ]; + ResourceManager rm = new ResourceManager("DateStrings", + typeof(Example).Assembly); + + foreach (var cultureName in cultureNames) { + CultureInfo culture = CultureInfo.CreateSpecificCulture(cultureName); + Thread.CurrentThread.CurrentCulture = culture; + Thread.CurrentThread.CurrentUICulture = culture; + + Console.WriteLine($"Current UI Culture: {CultureInfo.CurrentUICulture.Name}"); + string dateString = rm.GetString("DateStart"); + Console.WriteLine($"{dateString} {DateTime.Now:M}.\n"); + } + } +} + +// The example displays output similar to the following: +// Current UI Culture: en-US +// Today is February 03. +// +// Current UI Culture: fr-FR +// Aujourd'hui, c'est le 3 février +// +// Current UI Culture: ru-RU +// Сегодня февраля 03. +// +// Current UI Culture: sv-SE +// Today is den 3 februari. +// diff --git a/snippets/csharp/System.Resources/MissingManifestResourceException/Overview/showdate2.cs b/snippets/csharp/System.Resources/MissingManifestResourceException/Overview/showdate2.cs new file mode 100644 index 00000000000..21ba118be80 --- /dev/null +++ b/snippets/csharp/System.Resources/MissingManifestResourceException/Overview/showdate2.cs @@ -0,0 +1,32 @@ +// +using System; +using System.Globalization; +using System.Resources; +using System.Threading; + +public class Example2 +{ + public static void Main() + { + Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("ru-RU"); + Thread.CurrentThread.CurrentUICulture = CultureInfo.CreateSpecificCulture("ru-RU"); + + string[] cultureNames = [ "fr-FR", "sv-SE" ]; + ResourceManager rm = new ResourceManager("DateStrings", + typeof(Example).Assembly); + + foreach (var cultureName in cultureNames) + { + CultureInfo culture = CultureInfo.CreateSpecificCulture(cultureName); + string dateString = rm.GetString("DateStart", culture); + Console.WriteLine($"{culture.DisplayName}: {dateString} {DateTime.Now.ToString("M", culture)}."); + Console.WriteLine(); + } + } +} + +// The example displays output similar to the following: +// French (France): Aujourd'hui, c'est le 7 février. +// +// Swedish (Sweden): Today is den 7 februari. +// diff --git a/snippets/csharp/System.Resources/MissingManifestResourceException/Overview/showtime.cs b/snippets/csharp/System.Resources/MissingManifestResourceException/Overview/showtime.cs new file mode 100644 index 00000000000..2eb5aee56fb --- /dev/null +++ b/snippets/csharp/System.Resources/MissingManifestResourceException/Overview/showtime.cs @@ -0,0 +1,18 @@ +// +using System; +using System.Resources; + +public class ShowTimeEx +{ + public static void Main() + { + ResourceManager rm = new ResourceManager("Strings", + typeof(Example).Assembly); + string timeString = rm.GetString("TimeHeader"); + Console.WriteLine($"{timeString} {DateTime.Now:T}"); + } +} + +// The example displays output like the following: +// The current time is 2:03:14 PM +// diff --git a/snippets/csharp/System.Resources/NeutralResourcesLanguageAttribute/Overview/Project.csproj b/snippets/csharp/System.Resources/NeutralResourcesLanguageAttribute/Overview/Project.csproj new file mode 100644 index 00000000000..874c98f3477 --- /dev/null +++ b/snippets/csharp/System.Resources/NeutralResourcesLanguageAttribute/Overview/Project.csproj @@ -0,0 +1,8 @@ + + + + Library + net10.0 + + + diff --git a/snippets/csharp/System.Resources/NeutralResourcesLanguageAttribute/Overview/example.cs b/snippets/csharp/System.Resources/NeutralResourcesLanguageAttribute/Overview/example.cs new file mode 100644 index 00000000000..ca95766e331 --- /dev/null +++ b/snippets/csharp/System.Resources/NeutralResourcesLanguageAttribute/Overview/example.cs @@ -0,0 +1,30 @@ +// +using System; +using System.Globalization; +using System.Reflection; +using System.Resources; +using System.Threading; + +[assembly: NeutralResourcesLanguageAttribute("en")] +public class Example +{ + public static void Main() + { + // Select the current culture randomly to test resource fallback. + string[] cultures = { "de-DE", "en-us", "fr-FR" }; + Random rnd = new Random(); + int index = rnd.Next(0, cultures.Length); + Thread.CurrentThread.CurrentUICulture = CultureInfo.CreateSpecificCulture(cultures[index]); + Console.WriteLine($"The current culture is {CultureInfo.CurrentUICulture.Name}"); + + // Retrieve the resource. + ResourceManager rm = new ResourceManager("ExampleResources", + typeof(Example).Assembly); + string greeting = rm.GetString("Greeting"); + + Console.Write("Enter your name: "); + string name = Console.ReadLine(); + Console.WriteLine($"{greeting} {name}!"); + } +} +// diff --git a/snippets/csharp/System.Resources/ResourceManager/.ctor/Project.csproj b/snippets/csharp/System.Resources/ResourceManager/.ctor/Project.csproj new file mode 100644 index 00000000000..874c98f3477 --- /dev/null +++ b/snippets/csharp/System.Resources/ResourceManager/.ctor/Project.csproj @@ -0,0 +1,8 @@ + + + + Library + net10.0 + + + diff --git a/snippets/csharp/System.Resources/ResourceManager/.ctor/ctor1.cs b/snippets/csharp/System.Resources/ResourceManager/.ctor/ctor1.cs new file mode 100644 index 00000000000..3c829904f4a --- /dev/null +++ b/snippets/csharp/System.Resources/ResourceManager/.ctor/ctor1.cs @@ -0,0 +1,15 @@ +using System; +using System.Resources; + +public class Example +{ + public static void Main() + { + // + ResourceManager rm = new ResourceManager(typeof(Resource1)); + // + } +} + +internal class Resource1 +{ } \ No newline at end of file diff --git a/snippets/csharp/System.Resources/ResourceManager/.ctor/example.cs b/snippets/csharp/System.Resources/ResourceManager/.ctor/example.cs new file mode 100644 index 00000000000..628678dc8ec --- /dev/null +++ b/snippets/csharp/System.Resources/ResourceManager/.ctor/example.cs @@ -0,0 +1,23 @@ +// +using System; +using System.Reflection; +using System.Resources; + +public class Example1 +{ + public static void Main() + { + // Retrieve the resource. + ResourceManager rm = new ResourceManager("ExampleResources", + typeof(Example).Assembly); + string greeting = rm.GetString("Greeting"); + + Console.Write("Enter your name: "); + string name = Console.ReadLine(); + Console.WriteLine($"{greeting} {name}!"); + } +} +// The example produces output similar to the following: +// Enter your name: John +// Hello John! +// diff --git a/snippets/csharp/System.Resources/ResourceManager/.ctor/greet.cs b/snippets/csharp/System.Resources/ResourceManager/.ctor/greet.cs new file mode 100644 index 00000000000..089dd80f7a4 --- /dev/null +++ b/snippets/csharp/System.Resources/ResourceManager/.ctor/greet.cs @@ -0,0 +1,51 @@ +// +using System; +using System.Resources; +using System.Globalization; +using System.Threading; + +[assembly: NeutralResourcesLanguage("en")] + +public class Example2 +{ + public static void Main() + { + string[] cultureNames = [ "en-US", "fr-FR", "ru-RU", "sv-SE" ]; + DateTime noon = new DateTime(DateTime.Now.Year, DateTime.Now.Month, + DateTime.Now.Day, 12, 0, 0); + DateTime evening = new DateTime(DateTime.Now.Year, DateTime.Now.Month, + DateTime.Now.Day, 18, 0, 0); + + ResourceManager rm = new ResourceManager(typeof(GreetingResources)); + + foreach (var cultureName in cultureNames) + { + Thread.CurrentThread.CurrentUICulture = CultureInfo.CreateSpecificCulture(cultureName); + Console.WriteLine($"The current UI culture is {CultureInfo.CurrentUICulture.Name}"); + if (DateTime.Now < noon) + Console.WriteLine($"{rm.GetString("Morning")}!"); + else if (DateTime.Now < evening) + Console.WriteLine($"{rm.GetString("Afternoon")}!"); + else + Console.WriteLine($"{rm.GetString("Evening")}!"); + Console.WriteLine(); + } + } + + internal class GreetingResources + { + } +} +// The example displays output like the following: +// The current UI culture is en-US +// Good afternoon! +// +// The current UI culture is fr-FR +// Bonjour! +// +// The current UI culture is ru-RU +// Добрый день! +// +// The current UI culture is sv-SE +// Good afternoon! +// diff --git a/snippets/csharp/System.Resources/ResourceManager/GetObject/Project.csproj b/snippets/csharp/System.Resources/ResourceManager/GetObject/Project.csproj new file mode 100644 index 00000000000..731773ec4d6 --- /dev/null +++ b/snippets/csharp/System.Resources/ResourceManager/GetObject/Project.csproj @@ -0,0 +1,13 @@ + + + + Library + net48 + 12 + + + + + + + diff --git a/snippets/csharp/System.Resources/ResourceManager/GetObject/createresources.cs b/snippets/csharp/System.Resources/ResourceManager/GetObject/createresources.cs new file mode 100644 index 00000000000..4863188be2e --- /dev/null +++ b/snippets/csharp/System.Resources/ResourceManager/GetObject/createresources.cs @@ -0,0 +1,64 @@ +// +using System; +using System.Resources; + +public class CreateResource +{ + public static void Main() + { + Numbers en = new Numbers("one", "two", "three", "four", "five", + "six", "seven", "eight", "nine", "ten"); + CreateResourceFile(en, "en"); + Numbers fr = new Numbers("un", "deux", "trois", "quatre", "cinq", + "six", "sept", "huit", "neuf", "dix"); + CreateResourceFile(fr, "fr"); + Numbers pt = new Numbers("um", "dois", "três", "quatro", "cinco", + "seis", "sete", "oito", "nove", "dez"); + CreateResourceFile(pt, "pt"); + Numbers ru = new Numbers("один", "два", "три", "четыре", "пять", + "шесть", "семь", "восемь", "девять", "десять"); + CreateResourceFile(ru, "ru"); + } + + public static void CreateResourceFile(Numbers n, string lang) + { + string filename = @".\NumberResources" + + (lang != "en" ? "." + lang : "" ) + + ".resx"; + ResXResourceWriter rr = new ResXResourceWriter(filename); + rr.AddResource("Numbers", n); + rr.Generate(); + rr.Close(); + } +} +// + +[Serializable] public class Numbers +{ + public readonly string One; + public readonly string Two; + public readonly string Three; + public readonly string Four; + public readonly string Five; + public readonly string Six; + public readonly string Seven; + public readonly string Eight; + public readonly string Nine; + public readonly string Ten; + + public Numbers(string one, string two, string three, string four, + string five, string six, string seven, string eight, + string nine, string ten) + { + this.One = one; + this.Two = two; + this.Three = three; + this.Four = four; + this.Five = five; + this.Six = six; + this.Seven = seven; + this.Eight = eight; + this.Nine = nine; + this.Ten = ten; + } +} diff --git a/snippets/csharp/System.Resources/ResourceManager/GetObject/numberinfo.cs b/snippets/csharp/System.Resources/ResourceManager/GetObject/numberinfo.cs new file mode 100644 index 00000000000..dc06110ebd9 --- /dev/null +++ b/snippets/csharp/System.Resources/ResourceManager/GetObject/numberinfo.cs @@ -0,0 +1,33 @@ +// +using System; + +[Serializable] public class Numbers2 +{ + public readonly string One; + public readonly string Two; + public readonly string Three; + public readonly string Four; + public readonly string Five; + public readonly string Six; + public readonly string Seven; + public readonly string Eight; + public readonly string Nine; + public readonly string Ten; + + public Numbers2(string one, string two, string three, string four, + string five, string six, string seven, string eight, + string nine, string ten) + { + this.One = one; + this.Two = two; + this.Three = three; + this.Four = four; + this.Five = five; + this.Six = six; + this.Seven = seven; + this.Eight = eight; + this.Nine = nine; + this.Ten = ten; + } +} +// diff --git a/snippets/csharp/System.Resources/ResourceManager/GetObject/shownumbers.cs b/snippets/csharp/System.Resources/ResourceManager/GetObject/shownumbers.cs new file mode 100644 index 00000000000..d5e9e63e031 --- /dev/null +++ b/snippets/csharp/System.Resources/ResourceManager/GetObject/shownumbers.cs @@ -0,0 +1,74 @@ +// +using System; +using System.Globalization; +using System.Resources; +using System.Threading; + +[assembly:NeutralResourcesLanguageAttribute("en-US")] + +public class Example +{ + static string[] cultureNames = [ "fr-FR", "pt-BR", "ru-RU" ]; + + public static void Main() + { + // Make any non-default culture the current culture. + Random rnd = new Random(); + CultureInfo culture = CultureInfo.CreateSpecificCulture(cultureNames[rnd.Next(0, cultureNames.Length)]); + Thread.CurrentThread.CurrentUICulture = culture; + Console.WriteLine($"The current culture is {CultureInfo.CurrentUICulture.Name}\n"); + CultureInfo enCulture = CultureInfo.CreateSpecificCulture("en-US"); + + ResourceManager rm = new ResourceManager(typeof(NumberResources)); + Numbers numbers = (Numbers) rm.GetObject("Numbers"); + Numbers numbersEn = (Numbers) rm.GetObject("Numbers", enCulture); + Console.WriteLine($"{numbers.One} --> {numbersEn.One}"); + Console.WriteLine($"{numbers.Three} --> {numbersEn.Three}"); + Console.WriteLine($"{numbers.Five} --> {numbersEn.Five}"); + Console.WriteLine($"{numbers.Seven} --> {numbersEn.Seven}"); + Console.WriteLine($"{numbers.Nine} --> {numbersEn.Nine}\n"); + } +} + +internal class NumberResources +{ +} +// The example displays output like the following: +// The current culture is pt-BR +// +// um --> one +// três --> three +// cinco --> five +// sete --> seven +// nove --> nine +// + +[Serializable] public class Numbers3 +{ + public readonly string One; + public readonly string Two; + public readonly string Three; + public readonly string Four; + public readonly string Five; + public readonly string Six; + public readonly string Seven; + public readonly string Eight; + public readonly string Nine; + public readonly string Ten; + + public Numbers3(string one, string two, string three, string four, + string five, string six, string seven, string eight, + string nine, string ten) + { + this.One = one; + this.Two = two; + this.Three = three; + this.Four = four; + this.Five = five; + this.Six = six; + this.Seven = seven; + this.Eight = eight; + this.Nine = nine; + this.Ten = ten; + } +} diff --git a/snippets/csharp/System.Resources/ResourceManager/Overview/Project.csproj b/snippets/csharp/System.Resources/ResourceManager/Overview/Project.csproj new file mode 100644 index 00000000000..82288af1c7a --- /dev/null +++ b/snippets/csharp/System.Resources/ResourceManager/Overview/Project.csproj @@ -0,0 +1,12 @@ + + + + Library + net48 + + + + + + + diff --git a/snippets/csharp/System.Resources/ResourceManager/Overview/createresources.cs b/snippets/csharp/System.Resources/ResourceManager/Overview/createresources.cs index 98dff8dff3d..b5d3a7b736b 100644 --- a/snippets/csharp/System.Resources/ResourceManager/Overview/createresources.cs +++ b/snippets/csharp/System.Resources/ResourceManager/Overview/createresources.cs @@ -5,7 +5,7 @@ using System.IO; using System.Resources; -public class Example +public class CreateResourcesExample { public static void Main() { @@ -19,4 +19,4 @@ public static void Main() writer.Close(); } } -// \ No newline at end of file +// diff --git a/snippets/csharp/System.Resources/ResourceManager/Overview/ctor1.cs b/snippets/csharp/System.Resources/ResourceManager/Overview/ctor1.cs new file mode 100644 index 00000000000..0b805208659 --- /dev/null +++ b/snippets/csharp/System.Resources/ResourceManager/Overview/ctor1.cs @@ -0,0 +1,30 @@ +using System.Resources; + +public class CtorExample +{ + public static void Main() + { + CallCtor1(); + CallCtor2(); + } + + static void CallCtor1() + { + // + ResourceManager rm = new ResourceManager("MyCompany.StringResources", + typeof(CtorExample).Assembly); + // + } + + static void CallCtor2() + { + // + ResourceManager rm = new ResourceManager(typeof(MyCompany.StringResources)); + // + } +} + +namespace MyCompany +{ + class StringResources { } +} diff --git a/snippets/csharp/System.Resources/ResourceManager/Overview/example.cs b/snippets/csharp/System.Resources/ResourceManager/Overview/example.cs new file mode 100644 index 00000000000..e4d7eb05f08 --- /dev/null +++ b/snippets/csharp/System.Resources/ResourceManager/Overview/example.cs @@ -0,0 +1,41 @@ +// +using System; +using System.Globalization; +using System.Resources; +using System.Threading; + +public class Example1 +{ + public static void Main() + { + // Create array of supported cultures + string[] cultures = { "en-CA", "en-US", "fr-FR", "ru-RU" }; + Random rnd = new Random(); + int cultureNdx = rnd.Next(0, cultures.Length); + CultureInfo originalCulture = Thread.CurrentThread.CurrentCulture; + ResourceManager rm = new ResourceManager("Greetings", typeof(Example1).Assembly); + try + { + CultureInfo newCulture = new CultureInfo(cultures[cultureNdx]); + Thread.CurrentThread.CurrentCulture = newCulture; + Thread.CurrentThread.CurrentUICulture = newCulture; + string greeting = String.Format("The current culture is {0}.\n{1}", + Thread.CurrentThread.CurrentUICulture.Name, + rm.GetString("HelloString")); + Console.WriteLine(greeting); + } + catch (CultureNotFoundException e) + { + Console.WriteLine($"Unable to instantiate culture {e.InvalidCultureName}"); + } + finally + { + Thread.CurrentThread.CurrentCulture = originalCulture; + Thread.CurrentThread.CurrentUICulture = originalCulture; + } + } +} +// The example displays output like the following: +// The current culture is ru-RU. +// Всем привет! +// diff --git a/snippets/csharp/System.Resources/ResourceManager/Overview/example1.cs b/snippets/csharp/System.Resources/ResourceManager/Overview/example1.cs new file mode 100644 index 00000000000..1663582493b --- /dev/null +++ b/snippets/csharp/System.Resources/ResourceManager/Overview/example1.cs @@ -0,0 +1,26 @@ +// +using System; + +[Serializable] public struct PersonTable +{ + public readonly int nColumns; + public readonly string column1; + public readonly string column2; + public readonly string column3; + public readonly int width1; + public readonly int width2; + public readonly int width3; + + public PersonTable(string column1, string column2, string column3, + int width1, int width2, int width3) + { + this.column1 = column1; + this.column2 = column2; + this.column3 = column3; + this.width1 = width1; + this.width2 = width2; + this.width3 = width3; + this.nColumns = typeof(PersonTable).GetFields().Length / 2; + } +} +// diff --git a/snippets/csharp/System.Resources/ResourceManager/Overview/example11.cs b/snippets/csharp/System.Resources/ResourceManager/Overview/example11.cs new file mode 100644 index 00000000000..742d0eec572 --- /dev/null +++ b/snippets/csharp/System.Resources/ResourceManager/Overview/example11.cs @@ -0,0 +1,41 @@ +// +using System; +using System.Resources; + +public class CreateResource +{ + public static void Main() + { + PersonTable table = new PersonTable("Name", "Employee Number", + "Age", 30, 18, 5); + ResXResourceWriter rr = new ResXResourceWriter(@".\UIResources.resx"); + rr.AddResource("TableName", "Employees of Acme Corporation"); + rr.AddResource("Employees", table); + rr.Generate(); + rr.Close(); + } +} +// + +[Serializable] public struct PersonTable2 +{ + public readonly int nColumns; + public readonly string column1; + public readonly string column2; + public readonly string column3; + public readonly int width1; + public readonly int width2; + public readonly int width3; + + public PersonTable2(string column1, string column2, string column3, + int width1, int width2, int width3) + { + this.column1 = column1; + this.column2 = column2; + this.column3 = column3; + this.width1 = width1; + this.width2 = width2; + this.width3 = width3; + this.nColumns = typeof(PersonTable).GetFields().Length / 2; + } +} diff --git a/snippets/csharp/System.Resources/ResourceManager/Overview/example2.cs b/snippets/csharp/System.Resources/ResourceManager/Overview/example2.cs new file mode 100644 index 00000000000..1a4b03d2b19 --- /dev/null +++ b/snippets/csharp/System.Resources/ResourceManager/Overview/example2.cs @@ -0,0 +1,56 @@ +// +using System; +using System.Resources; + +[assembly: NeutralResourcesLanguageAttribute("en")] + +public class Example2 +{ + public static void Main() + { + string fmtString = String.Empty; + ResourceManager rm = new ResourceManager("UIResources", typeof(Example2).Assembly); + string title = rm.GetString("TableName"); + PersonTable tableInfo = (PersonTable) rm.GetObject("Employees"); + + if (! String.IsNullOrEmpty(title)) { + fmtString = "{0," + ((Console.WindowWidth + title.Length) / 2).ToString() + "}"; + Console.WriteLine(fmtString, title); + Console.WriteLine(); + } + + for (int ctr = 1; ctr <= tableInfo.nColumns; ctr++) { + string columnName = "column" + ctr.ToString(); + string widthName = "width" + ctr.ToString(); + string value = tableInfo.GetType().GetField(columnName).GetValue(tableInfo).ToString(); + int width = (int) tableInfo.GetType().GetField(widthName).GetValue(tableInfo); + fmtString = "{0,-" + width.ToString() + "}"; + Console.Write(fmtString, value); + } + Console.WriteLine(); + } +} +// + +[Serializable] public struct PersonTable3 +{ + public readonly int nColumns; + public readonly string column1; + public readonly string column2; + public readonly string column3; + public readonly int width1; + public readonly int width2; + public readonly int width3; + + public PersonTable3(string column1, string column2, string column3, + int width1, int width2, int width3) + { + this.column1 = column1; + this.column2 = column2; + this.column3 = column3; + this.width1 = width1; + this.width2 = width2; + this.width3 = width3; + this.nColumns = typeof(PersonTable).GetFields().Length / 2; + } +} diff --git a/snippets/csharp/System.Resources/ResourceManager/Overview/getstream.cs b/snippets/csharp/System.Resources/ResourceManager/Overview/getstream.cs index 49184c09503..e63d3d28893 100644 --- a/snippets/csharp/System.Resources/ResourceManager/Overview/getstream.cs +++ b/snippets/csharp/System.Resources/ResourceManager/Overview/getstream.cs @@ -1,15 +1,13 @@ // -using System; using System.Drawing; -using System.IO; using System.Resources; using System.Windows.Forms; -public class Example +public class Example3 { public static void Main() { - ResourceManager rm = new ResourceManager("AppResources", typeof(Example).Assembly); + ResourceManager rm = new ResourceManager("AppResources", typeof(Example3).Assembly); Bitmap screen = (Bitmap) Image.FromStream(rm.GetStream("SplashScreen")); Form frm = new Form(); diff --git a/snippets/csharp/System.Resources/ResourceManager/Overview/rmc.cs b/snippets/csharp/System.Resources/ResourceManager/Overview/rmc.cs new file mode 100644 index 00000000000..79d3e3d292e --- /dev/null +++ b/snippets/csharp/System.Resources/ResourceManager/Overview/rmc.cs @@ -0,0 +1,67 @@ +// +using System; +using System.Globalization; +using System.Resources; + +class Example4 +{ + public static void Main() + { + string day; + string year; + string holiday; + string celebrate = "{0} will occur on {1} in {2}.\n"; + + // Create a resource manager. + ResourceManager rm = new ResourceManager("rmc", + typeof(Example4).Assembly); + + Console.WriteLine("Obtain resources using the current UI culture."); + + // Get the resource strings for the day, year, and holiday + // using the current UI culture. + day = rm.GetString("day"); + year = rm.GetString("year"); + holiday = rm.GetString("holiday"); + Console.WriteLine(celebrate, holiday, day, year); + + // Obtain the es-MX culture. + CultureInfo ci = new CultureInfo("es-MX"); + + Console.WriteLine("Obtain resources using the es-MX culture."); + + // Get the resource strings for the day, year, and holiday + // using the specified culture. + day = rm.GetString("day", ci); + year = rm.GetString("year", ci); + holiday = rm.GetString("holiday", ci); + // --------------------------------------------------------------- + // Alternatively, comment the preceding 3 code statements and + // uncomment the following 4 code statements: + // ---------------------------------------------------------------- + // Set the current UI culture to "es-MX" (Spanish-Mexico). + // Thread.CurrentThread.CurrentUICulture = ci; + + // Get the resource strings for the day, year, and holiday + // using the current UI culture. Use those strings to + // display a message. + // day = rm.GetString("day"); + // year = rm.GetString("year"); + // holiday = rm.GetString("holiday"); + // --------------------------------------------------------------- + + // Regardless of the alternative that you choose, display a message + // using the retrieved resource strings. + Console.WriteLine(celebrate, holiday, day, year); + } +} +/* +This example displays the following output: + + Obtain resources using the current UI culture. + "5th of May" will occur on Friday in 2006. + + Obtain resources using the es-MX culture. + "Cinco de Mayo" will occur on Viernes in 2006. +*/ +// diff --git a/snippets/visualbasic/System.Resources/CurrentCulture/Overview/Project.vbproj b/snippets/visualbasic/System.Resources/CurrentCulture/Overview/Project.vbproj new file mode 100644 index 00000000000..874c98f3477 --- /dev/null +++ b/snippets/visualbasic/System.Resources/CurrentCulture/Overview/Project.vbproj @@ -0,0 +1,8 @@ + + + + Library + net10.0 + + + diff --git a/snippets/visualbasic/System.Resources/CurrentCulture/Overview/example.vb b/snippets/visualbasic/System.Resources/CurrentCulture/Overview/example.vb new file mode 100644 index 00000000000..0b00c9d5ea0 --- /dev/null +++ b/snippets/visualbasic/System.Resources/CurrentCulture/Overview/example.vb @@ -0,0 +1,34 @@ +' +Imports System.Globalization +Imports System.Resources +Imports System.Threading + +Module Example + Sub Main() + ' Create array of supported cultures + Dim cultures() As String = {"en-CA", "en-US", "fr-FR", "ru-RU" } + Dim rnd As New Random() + Dim cultureNdx As Integer = rnd.Next(0, cultures.Length) + Dim originalCulture As CultureInfo = Thread.CurrentThread.CurrentCulture + Dim rm As New ResourceManager("Greetings", GetType(Example).Assembly) + Try + Dim newCulture As New CultureInfo(cultures(cultureNdx)) + Thread.CurrentThread.CurrentCulture = newCulture + Thread.CurrentThread.CurrentUICulture = newCulture + Dim greeting As String = String.Format("The current culture is {0}.{1}{2}", + Thread.CurrentThread.CurrentUICulture.Name, + vbCrLf, rm.GetString("HelloString")) + + Console.WriteLine(greeting) + Catch e As CultureNotFoundException + Console.WriteLine("Unable to instantiate culture {0}", e.InvalidCultureName) + Finally + Thread.CurrentThread.CurrentCulture = originalCulture + Thread.CurrentThread.CurrentUICulture = originalCulture + End Try + End Sub +End Module +' The example displays output like the following: +' The current culture is ru-RU. +' Всем привет! +' \ No newline at end of file diff --git a/snippets/visualbasic/System.Resources/MissingManifestResourceException/Overview/Project.vbproj b/snippets/visualbasic/System.Resources/MissingManifestResourceException/Overview/Project.vbproj new file mode 100644 index 00000000000..874c98f3477 --- /dev/null +++ b/snippets/visualbasic/System.Resources/MissingManifestResourceException/Overview/Project.vbproj @@ -0,0 +1,8 @@ + + + + Library + net10.0 + + + diff --git a/snippets/visualbasic/System.Resources/MissingManifestResourceException/Overview/resourcenames.vb b/snippets/visualbasic/System.Resources/MissingManifestResourceException/Overview/resourcenames.vb new file mode 100644 index 00000000000..d52cac32cd3 --- /dev/null +++ b/snippets/visualbasic/System.Resources/MissingManifestResourceException/Overview/resourcenames.vb @@ -0,0 +1,37 @@ +' Visual Basic .NET Document +Option Strict On + +' +Imports System.IO +Imports System.Reflection +Imports System.Resources + +Module Example + Public Sub Main() + If Environment.GetCommandLineArgs.Length = 1 Then + Console.WriteLine("No filename.") + Exit Sub + End If + Dim filename As String = Environment.GetCommandLineArgs(1).Trim() + ' Check whether the file exists. + If Not File.Exists(filename) Then + Console.WriteLine("{0} does not exist.", filename) + Exit Sub + End If + + ' Try to load the assembly. + Dim assem As Assembly = Assembly.LoadFrom(filename) + Console.WriteLine("File: {0}", filename) + + ' Enumerate the resource files. + Dim resNames() As String = assem.GetManifestResourceNames() + If resNames.Length = 0 Then + Console.WriteLine(" No resources found.") + End If + For Each resName In resNames + Console.WriteLine(" Resource: {0}", resName.Replace(".resources", "")) + Next + Console.WriteLine() + End Sub +End Module +' diff --git a/snippets/visualbasic/System.Resources/NeutralResourcesLanguageAttribute/Overview/Project.vbproj b/snippets/visualbasic/System.Resources/NeutralResourcesLanguageAttribute/Overview/Project.vbproj new file mode 100644 index 00000000000..874c98f3477 --- /dev/null +++ b/snippets/visualbasic/System.Resources/NeutralResourcesLanguageAttribute/Overview/Project.vbproj @@ -0,0 +1,8 @@ + + + + Library + net10.0 + + + diff --git a/snippets/visualbasic/System.Resources/NeutralResourcesLanguageAttribute/Overview/example.vb b/snippets/visualbasic/System.Resources/NeutralResourcesLanguageAttribute/Overview/example.vb new file mode 100644 index 00000000000..52a0222df66 --- /dev/null +++ b/snippets/visualbasic/System.Resources/NeutralResourcesLanguageAttribute/Overview/example.vb @@ -0,0 +1,30 @@ +' Visual Basic .NET Document +Option Strict On + +' +Imports System.Globalization +Imports System.Resources +Imports System.Threading + + + +Module Example + Public Sub Main() + ' Select the current culture randomly to test resource fallback. + Dim cultures() As String = { "de-DE", "en-us", "fr-FR" } + Dim rnd As New Random() + Dim index As Integer = rnd.Next(0, cultures.Length) + Thread.CurrentThread.CurrentUICulture = CultureInfo.CreateSpecificCulture(cultures(index)) + Console.WriteLine("The current culture is {0}", + CultureInfo.CurrentUICulture.Name) + + ' Retrieve the resource. + Dim rm As New ResourceManager("ExampleResources" , GetType(Example).Assembly) + Dim greeting As String = rm.GetString("Greeting") + + Console.Write("Enter your name: ") + Dim name As String = Console.ReadLine() + Console.WriteLine("{0} {1}", greeting, name) + End Sub +End Module +' diff --git a/snippets/visualbasic/System.Resources/ResourceManager/.ctor/Project.vbproj b/snippets/visualbasic/System.Resources/ResourceManager/.ctor/Project.vbproj new file mode 100644 index 00000000000..874c98f3477 --- /dev/null +++ b/snippets/visualbasic/System.Resources/ResourceManager/.ctor/Project.vbproj @@ -0,0 +1,8 @@ + + + + Library + net10.0 + + + diff --git a/snippets/visualbasic/System.Resources/ResourceManager/.ctor/example.vb b/snippets/visualbasic/System.Resources/ResourceManager/.ctor/example.vb new file mode 100644 index 00000000000..ab61a6bf995 --- /dev/null +++ b/snippets/visualbasic/System.Resources/ResourceManager/.ctor/example.vb @@ -0,0 +1,24 @@ +' Visual Basic .NET Document +Option Strict On + +' +Imports System.Globalization +Imports System.Reflection +Imports System.Resources + +Module Example1 + Public Sub Main() + ' Retrieve the resource. + Dim rm As New ResourceManager("ExampleResources", + GetType(Example).Assembly) + Dim greeting As String = rm.GetString("Greeting") + + Console.Write("Enter your name: ") + Dim name As String = Console.ReadLine() + Console.WriteLine("{0} {1}!", greeting, name) + End Sub +End Module +' The example produces output similar to the following: +' Enter your name: John +' Hello John! +' diff --git a/snippets/visualbasic/System.Resources/ResourceManager/.ctor/greet.vb b/snippets/visualbasic/System.Resources/ResourceManager/.ctor/greet.vb new file mode 100644 index 00000000000..cca544a6a4e --- /dev/null +++ b/snippets/visualbasic/System.Resources/ResourceManager/.ctor/greet.vb @@ -0,0 +1,51 @@ +' Visual Basic .NET Document +Option Strict On + +' +Imports System.Resources +Imports System.Globalization +Imports System.Threading + + + +Module Example + Public Sub Main() + Dim cultureNames() As String = {"en-US", "fr-FR", "ru-RU", "sv-SE" } + Dim noon As New Date(Date.Now.Year, Date.Now.Month, + Date.Now.Day, 12,0,0) + Dim evening As New Date(Date.Now.Year, Date.Now.Month, + Date.Now.Day, 18, 0, 0) + + Dim rm As New ResourceManager(GetType(GreetingResources)) + + For Each cultureName In cultureNames + Thread.CurrentThread.CurrentUICulture = CultureInfo.CreateSpecificCulture(cultureName) + Console.WriteLine("The current UI culture is {0}", + CultureInfo.CurrentUICulture.Name) + If Date.Now < noon Then + Console.WriteLine("{0}!", rm.GetString("Morning")) + ElseIf Date.Now < evening Then + Console.WriteLine("{0}!", rm.GetString("Afternoon")) + Else + Console.WriteLine("{0}!", rm.GetString("Evening")) + End If + Console.WriteLine() + Next + End Sub +End Module + +Friend Class GreetingResources +End Class +' The example displays output like the following: +' The current UI culture is en-US +' Good afternoon! +' +' The current UI culture is fr-FR +' Bonjour! +' +' The current UI culture is ru-RU +' Добрый день! +' +' The current UI culture is sv-SE +' Good afternoon! +' diff --git a/snippets/visualbasic/System.Resources/ResourceManager/GetObject/Project.vbproj b/snippets/visualbasic/System.Resources/ResourceManager/GetObject/Project.vbproj new file mode 100644 index 00000000000..82288af1c7a --- /dev/null +++ b/snippets/visualbasic/System.Resources/ResourceManager/GetObject/Project.vbproj @@ -0,0 +1,12 @@ + + + + Library + net48 + + + + + + + diff --git a/snippets/visualbasic/System.Resources/ResourceManager/GetObject/createresources.vb b/snippets/visualbasic/System.Resources/ResourceManager/GetObject/createresources.vb new file mode 100644 index 00000000000..34da5fc0ed4 --- /dev/null +++ b/snippets/visualbasic/System.Resources/ResourceManager/GetObject/createresources.vb @@ -0,0 +1,61 @@ +' Visual Basic .NET Document +Option Strict On + +' +Imports System.Resources + +Module CreateResource + Public Sub Main() + Dim en As New Numbers("one", "two", "three", "four", "five", + "six", "seven", "eight", "nine", "ten") + CreateResourceFile(en, "en") + Dim fr As New Numbers("un", "deux", "trois", "quatre", "cinq", + "six", "sept", "huit", "neuf", "dix") + CreateResourceFile(fr, "fr") + Dim pt As New Numbers("um", "dois", "três", "quatro", "cinco", + "seis", "sete", "oito", "nove", "dez") + CreateResourceFile(pt, "pt") + Dim ru As New Numbers("один", "два", "три", "четыре", "пять", + "шесть", "семь", "восемь", "девять", "десять") + CreateResourceFile(ru, "ru") + End Sub + + Public Sub CreateResourceFile(n As Numbers, lang As String) + Dim filename As String = ".\NumberResources" + + If(lang <> "en", "." + lang, "") + + ".resx" + Dim rr As New ResXResourceWriter(filename) + rr.AddResource("Numbers", n) + rr.Generate() + rr.Close() + End Sub +End Module +' + + Public Class Numbers + Public Readonly One As String + Public ReadOnly Two As String + Public ReadOnly Three As String + Public ReadOnly Four As String + Public ReadOnly Five As String + Public ReadOnly Six As String + Public ReadOnly Seven As String + Public ReadOnly Eight As String + Public ReadOnly Nine As String + Public ReadOnly Ten As String + + Public Sub New(one As String, two As String, three As String, four As String, + five As String, six As String, seven As String, eight As String, + nine As String, ten As String) + Me.One = one + Me.Two = two + Me.Three = three + Me.Four = four + Me.Five = five + Me.Six = six + Me.Seven = seven + Me.Eight = eight + Me.Nine = nine + Me.Ten = ten + End Sub +End Class diff --git a/snippets/visualbasic/System.Resources/ResourceManager/GetObject/example.vb b/snippets/visualbasic/System.Resources/ResourceManager/GetObject/example.vb new file mode 100644 index 00000000000..bed4c85d6b2 --- /dev/null +++ b/snippets/visualbasic/System.Resources/ResourceManager/GetObject/example.vb @@ -0,0 +1,44 @@ +' Visual Basic .NET Document +Option Strict On + +' The following is CreateResources.* +' +Imports System.Resources + +Module CreateResource1 + Public Sub Main() + Dim table As New PersonTable("Name", "Employee Number", "Age", 30, 18, 5) + Dim rr As New ResXResourceWriter(".\UIResources.resx") + rr.AddResource("TableName", "Employees of Acme Corporation") + rr.AddResource("Employees", table) + rr.Generate() + rr.Close() + End Sub +End Module +' + + +' The following is UIElements.* +' + Public Structure PersonTable1 + Public ReadOnly nColumns As Integer + Public ReadOnly column1 As String + Public ReadOnly column2 As String + Public ReadOnly column3 As String + Public ReadOnly width1 As Integer + Public ReadOnly width2 As Integer + Public ReadOnly width3 As Integer + + Public Sub New(column1 As String, column2 As String, column3 As String, + width1 As Integer, width2 As Integer, width3 As Integer) + Me.column1 = column1 + Me.column2 = column2 + Me.column3 = column3 + Me.width1 = width1 + Me.width2 = width2 + Me.width3 = width3 + Me.nColumns = Me.GetType().GetFields().Count \ 2 + End Sub +End Structure +' + diff --git a/snippets/visualbasic/System.Resources/ResourceManager/GetObject/example2.vb b/snippets/visualbasic/System.Resources/ResourceManager/GetObject/example2.vb new file mode 100644 index 00000000000..e64ae2afeaf --- /dev/null +++ b/snippets/visualbasic/System.Resources/ResourceManager/GetObject/example2.vb @@ -0,0 +1,55 @@ +' Visual Basic .NET Document +Option Strict On + +' +Imports System.Resources + + + +Module Example + Public Sub Main() + Dim fmtString As String = String.Empty + Dim rm As New ResourceManager("UIResources", GetType(Example).Assembly) + Dim title As String = rm.GetString("TableName") + Dim tableInfo As PersonTable = DirectCast(rm.GetObject("Employees"), PersonTable) + + If Not String.IsNullOrEmpty(title) Then + fmtString = "{0," + ((Console.WindowWidth + title.Length) \ 2).ToString() + "}" + Console.WriteLine(fmtString, title) + Console.WriteLine() + End If + + For ctr As Integer = 1 To tableInfo.nColumns + Dim columnName As String = "column" + ctr.ToString() + Dim widthName As String = "width" + ctr.ToString() + Dim value As String = CStr(tableInfo.GetType().GetField(columnName).GetValue(tableInfo)) + Dim width As Integer = CInt(tableInfo.GetType().GetField(widthName).GetValue(tableInfo)) + fmtString = "{0,-" + width.ToString() + "}" + Console.Write(fmtString, value) + Next + Console.WriteLine() + End Sub +End Module +' + + Public Structure PersonTable + Public ReadOnly nColumns As Integer + Public Readonly column1 As String + Public ReadOnly column2 As String + Public ReadOnly column3 As String + Public ReadOnly width1 As Integer + Public ReadOnly width2 As Integer + Public ReadOnly width3 As Integer + + Public Sub New(column1 As String, column2 As String, column3 As String, + width1 As Integer, width2 As Integer, width3 As Integer) + Me.column1 = column1 + Me.column2 = column2 + Me.column3 = column3 + Me.width1 = width1 + Me.width2 = width2 + Me.width3 = width3 + Me.nColumns = Me.GetType().GetFields().Count \ 2 + End Sub +End Structure + diff --git a/snippets/visualbasic/System.Resources/ResourceManager/GetObject/numberinfo.vb b/snippets/visualbasic/System.Resources/ResourceManager/GetObject/numberinfo.vb new file mode 100644 index 00000000000..2aee0872b92 --- /dev/null +++ b/snippets/visualbasic/System.Resources/ResourceManager/GetObject/numberinfo.vb @@ -0,0 +1,29 @@ +' + Public Class Numbers2 + Public ReadOnly One As String + Public ReadOnly Two As String + Public ReadOnly Three As String + Public ReadOnly Four As String + Public ReadOnly Five As String + Public ReadOnly Six As String + Public ReadOnly Seven As String + Public ReadOnly Eight As String + Public ReadOnly Nine As String + Public ReadOnly Ten As String + + Public Sub New(one As String, two As String, three As String, four As String, + five As String, six As String, seven As String, eight As String, + nine As String, ten As String) + Me.One = one + Me.Two = two + Me.Three = three + Me.Four = four + Me.Five = five + Me.Six = six + Me.Seven = seven + Me.Eight = eight + Me.Nine = nine + Me.Ten = ten + End Sub +End Class +' diff --git a/snippets/visualbasic/System.Resources/ResourceManager/GetObject/shownumbers.vb b/snippets/visualbasic/System.Resources/ResourceManager/GetObject/shownumbers.vb new file mode 100644 index 00000000000..1fddd314f0c --- /dev/null +++ b/snippets/visualbasic/System.Resources/ResourceManager/GetObject/shownumbers.vb @@ -0,0 +1,73 @@ +' Visual Basic .NET Document +Option Strict On + +' +Imports System.Globalization +Imports System.Resources +Imports System.Threading + +Module Example2 + Dim cultureNames() As String = {"fr-FR", "pt-BR", "ru-RU"} + + Public Sub Main() + ' Make any non-default culture the current culture. + Dim rnd As New Random + Dim culture As CultureInfo = CultureInfo.CreateSpecificCulture(cultureNames(rnd.Next(0, cultureNames.Length))) + Thread.CurrentThread.CurrentUICulture = culture + Console.WriteLine("The current culture is {0}", CultureInfo.CurrentUICulture.Name) + Console.WriteLine() + Dim enCulture As CultureInfo = CultureInfo.CreateSpecificCulture("en-US") + + Dim rm As New ResourceManager(GetType(NumberResources)) + Dim numbers As Numbers = CType(rm.GetObject("Numbers"), Numbers) + Dim numbersEn As Numbers = CType(rm.GetObject("Numbers", enCulture), Numbers) + Console.WriteLine("{0} --> {1}", numbers.One, numbersEn.One) + Console.WriteLine("{0} --> {1}", numbers.Three, numbersEn.Three) + Console.WriteLine("{0} --> {1}", numbers.Five, numbersEn.Five) + Console.WriteLine("{0} --> {1}", numbers.Seven, numbersEn.Seven) + Console.WriteLine("{0} --> {1}", numbers.Nine, numbersEn.Nine) + Console.WriteLine() + End Sub +End Module + + +Friend Class NumberResources +End Class + +' The example displays output like the following: +' The current culture is pt-BR +' +' um --> one +' três --> three +' cinco --> five +' sete --> seven +' nove --> nine +' + + Public Class Numbers3 + Public ReadOnly One As String + Public ReadOnly Two As String + Public ReadOnly Three As String + Public ReadOnly Four As String + Public ReadOnly Five As String + Public ReadOnly Six As String + Public ReadOnly Seven As String + Public ReadOnly Eight As String + Public ReadOnly Nine As String + Public ReadOnly Ten As String + + Public Sub New(one As String, two As String, three As String, four As String, + five As String, six As String, seven As String, eight As String, + nine As String, ten As String) + Me.One = one + Me.Two = two + Me.Three = three + Me.Four = four + Me.Five = five + Me.Six = six + Me.Seven = seven + Me.Eight = eight + Me.Nine = nine + Me.Ten = ten + End Sub +End Class diff --git a/snippets/visualbasic/System.Resources/ResourceManager/GetString/Project.vbproj b/snippets/visualbasic/System.Resources/ResourceManager/GetString/Project.vbproj new file mode 100644 index 00000000000..874c98f3477 --- /dev/null +++ b/snippets/visualbasic/System.Resources/ResourceManager/GetString/Project.vbproj @@ -0,0 +1,8 @@ + + + + Library + net10.0 + + + diff --git a/snippets/visualbasic/System.Resources/ResourceManager/GetString/showdate.vb b/snippets/visualbasic/System.Resources/ResourceManager/GetString/showdate.vb new file mode 100644 index 00000000000..5b75d8c8c38 --- /dev/null +++ b/snippets/visualbasic/System.Resources/ResourceManager/GetString/showdate.vb @@ -0,0 +1,42 @@ +' Visual Basic .NET Document +Option Strict On + +' +Imports System.Globalization +Imports System.Resources +Imports System.Threading + + + +Module Example + Public Sub Main() + Dim cultureNames() As String = { "en-US", "fr-FR", "ru-RU", "sv-SE" } + Dim rm As New ResourceManager("DateStrings", + GetType(Example).Assembly) + + For Each cultureName In cultureNames + Dim culture As CultureInfo = CultureInfo.CreateSpecificCulture(cultureName) + Thread.CurrentThread.CurrentCulture = culture + Thread.CurrentThread.CurrentUICulture = culture + + Console.WriteLine("Current UI Culture: {0}", + CultureInfo.CurrentUICulture.Name) + Dim dateString As String = rm.GetString("DateStart") + Console.WriteLine("{0} {1:M}.", dateString, Date.Now) + Console.WriteLine() + Next + End Sub +End Module +' The example displays output similar to the following: +' Current UI Culture: en-US +' Today is February 03. +' +' Current UI Culture: fr-FR +' Aujourd'hui, c'est le 3 février +' +' Current UI Culture: ru-RU +' Сегодня февраля 03. +' +' Current UI Culture: sv-SE +' Today is den 3 februari. +' diff --git a/snippets/visualbasic/System.Resources/ResourceManager/GetString/showdate2.vb b/snippets/visualbasic/System.Resources/ResourceManager/GetString/showdate2.vb new file mode 100644 index 00000000000..7791d07210d --- /dev/null +++ b/snippets/visualbasic/System.Resources/ResourceManager/GetString/showdate2.vb @@ -0,0 +1,31 @@ +' Visual Basic .NET Document +Option Strict On + +' +Imports System.Globalization +Imports System.Resources +Imports System.Threading + +Module Example2 + Public Sub Main() + Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("ru-RU") + Thread.CurrentThread.CurrentUICulture = CultureInfo.CreateSpecificCulture("ru-RU") + + Dim cultureNames() As String = {"fr-FR", "sv-SE"} + Dim rm As New ResourceManager("DateStrings", + GetType(Example).Assembly) + + For Each cultureName In cultureNames + Dim culture As CultureInfo = CultureInfo.CreateSpecificCulture(cultureName) + Dim dateString As String = rm.GetString("DateStart", culture) + Console.WriteLine("{0}: {1} {2}.", culture.DisplayName, dateString, + Date.Now.ToString("M", culture)) + Console.WriteLine() + Next + End Sub +End Module +' The example displays output similar to the following: +' French (France): Aujourd'hui, c'est le 7 février. +' +' Swedish (Sweden): Today is den 7 februari. +' diff --git a/snippets/visualbasic/System.Resources/ResourceManager/Overview/Project.vbproj b/snippets/visualbasic/System.Resources/ResourceManager/Overview/Project.vbproj new file mode 100644 index 00000000000..874c98f3477 --- /dev/null +++ b/snippets/visualbasic/System.Resources/ResourceManager/Overview/Project.vbproj @@ -0,0 +1,8 @@ + + + + Library + net10.0 + + + diff --git a/snippets/visualbasic/System.Resources/ResourceManager/Overview/ctor1.vb b/snippets/visualbasic/System.Resources/ResourceManager/Overview/ctor1.vb new file mode 100644 index 00000000000..8bc71ab99cf --- /dev/null +++ b/snippets/visualbasic/System.Resources/ResourceManager/Overview/ctor1.vb @@ -0,0 +1,26 @@ +Imports System.Resources + +Public Module Example2 + Public Sub Main() + CallCtor1() + CallCtor2() + End Sub + + Sub CallCtor1() + ' + Dim rm As New ResourceManager("MyCompany.StringResources", + GetType(Example2).Assembly) + ' + End Sub + + Sub CallCtor2() + ' + Dim rm As New ResourceManager(GetType(MyCompany.StringResources)) + ' + End Sub +End Module + +Namespace MyCompany + Class StringResources + End Class +End Namespace diff --git a/snippets/visualbasic/System.Resources/ResourceManager/Overview/resourcenames.vb b/snippets/visualbasic/System.Resources/ResourceManager/Overview/resourcenames.vb new file mode 100644 index 00000000000..2aa627abb2d --- /dev/null +++ b/snippets/visualbasic/System.Resources/ResourceManager/Overview/resourcenames.vb @@ -0,0 +1,37 @@ +' Visual Basic .NET Document +Option Strict On + +' +Imports System.IO +Imports System.Reflection +Imports System.Resources + +Module Example3 + Public Sub Main() + If Environment.GetCommandLineArgs.Length = 1 Then + Console.WriteLine("No filename.") + Exit Sub + End If + Dim filename As String = Environment.GetCommandLineArgs(1).Trim() + ' Check whether the file exists. + If Not File.Exists(filename) Then + Console.WriteLine("{0} does not exist.", filename) + Exit Sub + End If + + ' Try to load the assembly. + Dim assem As Assembly = Assembly.LoadFrom(filename) + Console.WriteLine("File: {0}", filename) + + ' Enumerate the resource files. + Dim resNames() As String = assem.GetManifestResourceNames() + If resNames.Length = 0 Then + Console.WriteLine(" No resources found.") + End If + For Each resName In resNames + Console.WriteLine(" Resource: {0}", resName.Replace(".resources", "")) + Next + Console.WriteLine() + End Sub +End Module +' diff --git a/snippets/visualbasic/System.Resources/ResourceManager/Overview/rmc.vb b/snippets/visualbasic/System.Resources/ResourceManager/Overview/rmc.vb new file mode 100644 index 00000000000..5de1d0c30f0 --- /dev/null +++ b/snippets/visualbasic/System.Resources/ResourceManager/Overview/rmc.vb @@ -0,0 +1,61 @@ +' +Imports System.Resources +Imports System.Reflection +Imports System.Threading +Imports System.Globalization + +Class Example4 + Public Shared Sub Main() + Dim day As String + Dim year As String + Dim holiday As String + Dim celebrate As String = "{0} will occur on {1} in {2}." & vbCrLf + + ' Create a resource manager. + Dim rm As New ResourceManager("rmc", GetType(Example4).Assembly) + + Console.WriteLine("Obtain resources using the current UI culture.") + + ' Get the resource strings for the day, year, and holiday + ' using the current UI culture. + day = rm.GetString("day") + year = rm.GetString("year") + holiday = rm.GetString("holiday") + Console.WriteLine(celebrate, holiday, day, year) + + ' Obtain the es-MX culture. + Dim ci As New CultureInfo("es-MX") + + Console.WriteLine("Obtain resources using the es-MX culture.") + + ' Get the resource strings for the day, year, and holiday + ' using the es-MX culture. + day = rm.GetString("day", ci) + year = rm.GetString("year", ci) + holiday = rm.GetString("holiday", ci) + + ' --------------------------------------------------------------- + ' Alternatively, comment the preceding 3 code statements and + ' uncomment the following 4 code statements: + ' ---------------------------------------------------------------- + ' Set the current UI culture to "es-MX" (Spanish-Mexico). + ' Thread.CurrentThread.CurrentUICulture = ci + ' Get the resource strings for the day, year, and holiday + ' using the current UI culture. + ' day = rm.GetString("day") + ' year = rm.GetString("year") + ' holiday = rm.GetString("holiday") + ' --------------------------------------------------------------- + + ' Regardless of the alternative that you choose, display a message + ' using the retrieved resource strings. + Console.WriteLine(celebrate, holiday, day, year) + End Sub +End Class +' This example displays the following output: +'Obtain resources using the current UI culture. +'"5th of May" will occur on Friday in 2006. +' +'Obtain resources using the es-MX culture. +'"Cinco de Mayo" will occur on Viernes in 2006. +' diff --git a/snippets/visualbasic/System.Resources/ResourceManager/Overview/showdate.vb b/snippets/visualbasic/System.Resources/ResourceManager/Overview/showdate.vb new file mode 100644 index 00000000000..18ef5f69f97 --- /dev/null +++ b/snippets/visualbasic/System.Resources/ResourceManager/Overview/showdate.vb @@ -0,0 +1,42 @@ +' Visual Basic .NET Document +Option Strict On + +' +Imports System.Globalization +Imports System.Resources +Imports System.Threading + + + +Module Example5 + Public Sub Main() + Dim cultureNames() As String = {"en-US", "fr-FR", "ru-RU", "sv-SE"} + Dim rm As New ResourceManager("DateStrings", + GetType(Example5).Assembly) + + For Each cultureName In cultureNames + Dim culture As CultureInfo = CultureInfo.CreateSpecificCulture(cultureName) + Thread.CurrentThread.CurrentCulture = culture + Thread.CurrentThread.CurrentUICulture = culture + + Console.WriteLine("Current UI Culture: {0}", + CultureInfo.CurrentUICulture.Name) + Dim dateString As String = rm.GetString("DateStart") + Console.WriteLine("{0} {1:M}.", dateString, Date.Now) + Console.WriteLine() + Next + End Sub +End Module +' The example displays output similar to the following: +' Current UI Culture: en-US +' Today is February 03. +' +' Current UI Culture: fr-FR +' Aujourd'hui, c'est le 3 février +' +' Current UI Culture: ru-RU +' Сегодня февраля 03. +' +' Current UI Culture: sv-SE +' Today is den 3 februari. +' diff --git a/snippets/visualbasic/System.Resources/ResourceManager/Overview/showtime.vb b/snippets/visualbasic/System.Resources/ResourceManager/Overview/showtime.vb new file mode 100644 index 00000000000..880654e69b5 --- /dev/null +++ b/snippets/visualbasic/System.Resources/ResourceManager/Overview/showtime.vb @@ -0,0 +1,16 @@ +' Visual Basic .NET Document +Option Strict On + +' +Imports System.Resources + +Module Example6 + Public Sub Main() + Dim rm As New ResourceManager("Strings", GetType(Example6).Assembly) + Dim timeString As String = rm.GetString("TimeHeader") + Console.WriteLine("{0} {1:T}", timeString, Date.Now) + End Sub +End Module +' The example displays output similar to the following: +' The current time is 2:03:14 PM +' diff --git a/snippets/visualbasic/System.Resources/ResourceReader/Overview/Project.vbproj b/snippets/visualbasic/System.Resources/ResourceReader/Overview/Project.vbproj new file mode 100644 index 00000000000..874c98f3477 --- /dev/null +++ b/snippets/visualbasic/System.Resources/ResourceReader/Overview/Project.vbproj @@ -0,0 +1,8 @@ + + + + Library + net10.0 + + + diff --git a/snippets/visualbasic/System.Resources/ResourceReader/Overview/class1.vb b/snippets/visualbasic/System.Resources/ResourceReader/Overview/class1.vb new file mode 100644 index 00000000000..32cc54a9eb3 --- /dev/null +++ b/snippets/visualbasic/System.Resources/ResourceReader/Overview/class1.vb @@ -0,0 +1,37 @@ +' Visual Basic .NET Document +Option Strict On + +' +Imports System.Collections +Imports System.Resources + +Module Example2 + Public Sub Main() + Console.WriteLine("Resources in ApplicationResources.resources:") + Dim res As New ResourceReader(".\ApplicationResources.resources") + Dim dict As IDictionaryEnumerator = res.GetEnumerator() + Do While dict.MoveNext() + Console.WriteLine(" {0}: '{1}' (Type {2})", dict.Key, dict.Value, dict.Value.GetType().Name) + Loop + res.Close() + End Sub +End Module +' The example displays output like the following: +' Resources in ApplicationResources.resources: +' Label3: '"Last Name:"' (Type String) +' Label2: '"Middle Name:"' (Type String) +' Label1: '"First Name:"' (Type String) +' Label7: '"State:"' (Type String) +' Label6: '"City:"' (Type String) +' Label5: '"Street Address:"' (Type String) +' Label4: '"SSN:"' (Type String) +' Label9: '"Home Phone:"' (Type String) +' Label8: '"Zip Code:"' (Type String) +' Title: '"Contact Information"' (Type String) +' Label12: '"Other Phone:"' (Type String) +' Label13: '"Fax:"' (Type String) +' Label10: '"Business Phone:"' (Type String) +' Label11: '"Mobile Phone:"' (Type String) +' Label14: '"Email Address:"' (Type String) +' Label15: '"Alternate Email Address:"' (Type String) +' diff --git a/snippets/visualbasic/System.Resources/ResourceReader/Overview/ctor1.vb b/snippets/visualbasic/System.Resources/ResourceReader/Overview/ctor1.vb new file mode 100644 index 00000000000..9d0a3ce02f0 --- /dev/null +++ b/snippets/visualbasic/System.Resources/ResourceReader/Overview/ctor1.vb @@ -0,0 +1,46 @@ +' Visual Basic .NET Document +Option Strict On + +Module Example + Public Sub Main() + Standalone() + Console.WriteLine("---") + Embedded + End Sub + + Private Sub Standalone() + ' + ' Instantiate a standalone .resources file from its filename. + Dim rr1 As New System.Resources.ResourceReader("Resources1.resources") + + ' Instantiate a standalone .resources file from a stream. + Dim fs As New System.IO.FileStream(".\Resources2.resources", + System.IO.FileMode.Open) + Dim rr2 As New System.Resources.ResourceReader(fs) + ' + + Console.WriteLine("rr1: {0}", rr1 IsNot Nothing) + Console.WriteLine("rr2: {0}", rr2 IsNot Nothing) + End Sub + + Private Sub Embedded() + ' + Dim assem As System.Reflection.Assembly = + System.Reflection.Assembly.LoadFrom(".\MyLibrary.dll") + Dim fs As System.IO.Stream = + assem.GetManifestResourceStream("MyCompany.LibraryResources.resources") + Dim rr As New System.Resources.ResourceReader(fs) + ' + + If fs Is Nothing Then + Console.WriteLine(fs Is Nothing) + For Each name In assem.GetManifestResourceNames() + Console.WriteLine(name) + Next + Exit Sub + Else + Console.WriteLine(fs Is Nothing) + End If + End Sub +End Module + diff --git a/xml/System.Reflection.Emit/AssemblyBuilder.xml b/xml/System.Reflection.Emit/AssemblyBuilder.xml index c8e078fcbc2..2060cffd0af 100644 --- a/xml/System.Reflection.Emit/AssemblyBuilder.xml +++ b/xml/System.Reflection.Emit/AssemblyBuilder.xml @@ -61,10 +61,47 @@ ## Remarks -For more information about this API, see [Supplemental API remarks for AssemblyBuilder](/dotnet/fundamentals/runtime-libraries/system-reflection-emit-assemblybuilder). +A dynamic assembly is an assembly that is created using the Reflection Emit APIs. A dynamic assembly can reference types defined in another dynamic or static assembly. You can use to generate dynamic assemblies in memory and execute their code during the same application run. .NET 9 introduced the type with a fully managed implementation of reflection emit that allows you to save the assembly to a file. A dynamic assembly can consist of only one dynamic module. + +## Runnable dynamic assemblies in .NET + +To get a runnable object, use the method. Dynamic assemblies can be created using one of the following access modes: + +- + + The dynamic assembly represented by an can be used to execute the emitted code. + +- + + The dynamic assembly represented by an can be used to execute the emitted code and is automatically reclaimed by garbage collector. + +The access mode must be specified by providing the appropriate value in the call to the method when the dynamic assembly is defined and cannot be changed later. The runtime uses the access mode of a dynamic assembly to optimize the assembly's internal representation. + +The following example demonstrates how to create and run an assembly: + +```csharp +public void CreateAndRunAssembly(string assemblyPath) +{ + AssemblyBuilder ab = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("MyAssembly"), AssemblyBuilderAccess.Run); + ModuleBuilder mob = ab.DefineDynamicModule("MyModule"); + TypeBuilder tb = mob.DefineType("MyType", TypeAttributes.Public | TypeAttributes.Class); + MethodBuilder mb = tb.DefineMethod("SumMethod", MethodAttributes.Public | MethodAttributes.Static, + typeof(int), new Type[] {typeof(int), typeof(int)}); + ILGenerator il = mb.GetILGenerator(); + il.Emit(OpCodes.Ldarg_0); + il.Emit(OpCodes.Ldarg_1); + il.Emit(OpCodes.Add); + il.Emit(OpCodes.Ret); + + Type type = tb.CreateType(); + + MethodInfo method = type.GetMethod("SumMethod"); + Console.WriteLine(method.Invoke(null, new object[] { 5, 10 })); +} +``` + +The type, which derives from , lets you save dynamic assemblies. For more information, see the usage scenarios and examples at . -> [!WARNING] -> `AssemblyBuilder` APIs require a fully trusted environment with trusted input, similar to other technologies such as compilers. There are no restrictions other than basic validation for generated IL that the `AssemblyBuilder` can contain. That includes validation for member name, count, and associated metadata, such as custom attributes. ]]> diff --git a/xml/System.Reflection.Emit/DynamicMethod.xml b/xml/System.Reflection.Emit/DynamicMethod.xml index 87c0c9f3f08..1ab2e5d20ce 100644 --- a/xml/System.Reflection.Emit/DynamicMethod.xml +++ b/xml/System.Reflection.Emit/DynamicMethod.xml @@ -50,7 +50,55 @@ Defines and represents a dynamic method that can be compiled, executed, and discarded. Discarded methods are available for garbage collection. - For more information about this API, see Supplemental API remarks for DynamicMethod. + + class to generate and execute a method at runtime, without having to generate a dynamic assembly and a dynamic type to contain the method. The executable code created by the just-in-time (JIT) compiler is reclaimed when the object is reclaimed. Dynamic methods are the most efficient way to generate and execute small amounts of code. + +A dynamic method can be anonymously hosted, or it can be logically associated with a module or with a type. + +- If the dynamic method is anonymously hosted, it is located in a system-provided assembly, and therefore is isolated from other code. By default, it does not have access to any non-public data. An anonymously hosted dynamic method can have restricted ability to skip the JIT compiler's visibility checks, if it has been granted with the flag. The trust level of the assembly whose non-public members are accessed by the dynamic method must be equal to, or a subset of, the trust level of the call stack that emitted the dynamic method. For more information about anonymously hosted dynamic methods, see [Walkthrough: Emitting Code in Partial Trust Scenarios](/dotnet/framework/reflection-and-codedom/walkthrough-emitting-code-in-partial-trust-scenarios). + +- If the dynamic method is associated with a module that you specify, the dynamic method is effectively global to that module. It can access all types in the module and all `internal` (`Friend` in Visual Basic) members of the types. You can associate a dynamic method with any module, regardless of whether you created the module, provided that a demand for with the flag can be satisfied by the call stack that includes your code. If the flag is included in the grant, the dynamic method can skip the JIT compiler's visibility checks and access the private data of all types declared in the module or in any other module in any assembly. + + > [!NOTE] + > When you specify the module with which a dynamic method is associated, that module must not be in the system-provided assembly that is used for anonymous hosting. + +- If the dynamic method is associated with a type that you specify, it has access to all members of the type, regardless of access level. In addition, JIT visibility checks can be skipped. This gives the dynamic method access to the private data of other types declared in the same module or in any other module in any assembly. You can associate a dynamic method with any type, but your code must be granted with both the and flags. + +The following table shows which types and members are accessible to an anonymously hosted dynamic method, with and without JIT visibility checks, depending on whether with the flag is granted. + +| Visibility checks | Without `RestrictedMemberAccess` | With `RestrictedMemberAccess` | +|-------------------|----------------------------------|-------------------------------| +|Without skipping JIT visibility checks|Public members of public types in any assembly.|Public members of public types in any assembly.| +|Skipping JIT visibility checks, with restrictions|Public members of public types in any assembly.|All members of all types, only in assemblies whose trust levels are equal to or less than the trust level of the assembly that emitted the dynamic method.| + +The following table shows which types and members are accessible to a dynamic method that's associated with a module or with a type in a module. + +| Skip JIT visibility checks | Associated with module | Associated with type | +|----------------------------|------------------------|----------------------| +| No |Public and internal members of public, internal, and private types in the module.

Public members of public types in any assembly.|All members of the associated type. Public and internal members of all the other types in the module.

Public members of public types in any assembly.| +| Yes |All members of all types in any assembly.|All members of all types in any assembly.| + +A dynamic method that is associated with a module has the permissions of that module. A dynamic method that is associated with a type has the permissions of the module containing that type. + +Dynamic methods and their parameters do not have to be named, but you can specify names to assist in debugging. Custom attributes are not supported on dynamic methods or their parameters. + +Although dynamic methods are `static` methods (`Shared` methods in Visual Basic), the relaxed rules for delegate binding allow a dynamic method to be bound to an object, so that it acts like an instance method when called using that delegate instance. An example that demonstrates this is provided for the method overload. + +## Verification + +The following list summarizes the conditions under which dynamic methods can contain unverifiable code. (For example, a dynamic method is unverifiable if its property is set to `false`.) + +- A dynamic method that's associated with a security-critical assembly is also security-critical, and can skip verification. For example, an assembly without security attributes that is run as a desktop application is treated as security-critical by the runtime. If you associate a dynamic method with the assembly, the dynamic method can contain unverifiable code. +- If a dynamic method that contains unverifiable code is associated with an assembly that has level 1 transparency, the just-in-time (JIT) compiler injects a security demand. The demand succeeds only if the dynamic method is executed by fully trusted code. See [Security-Transparent Code, Level 1](/dotnet/framework/misc/security-transparent-code-level-1). +- If a dynamic method that contains unverifiable code is associated with an assembly that has level 2 transparency (such as mscorlib.dll), it throws an exception (injected by the JIT compiler) instead of making a security demand. See [Security-Transparent Code, Level 2](/dotnet/framework/misc/security-transparent-code-level-2). +- An anonymously hosted dynamic method that contains unverifiable code always throws an exception. It can never skip verification, even if it is created and executed by fully trusted code. + +The exception that's thrown for unverifiable code varies depending on the way the dynamic method is invoked. If you invoke a dynamic method by using a delegate returned from the method, a is thrown. If you invoke the dynamic method by using the method, a is thrown with an inner . + + ]]>
+
method. diff --git a/xml/System.Reflection.Emit/MethodBuilder.xml b/xml/System.Reflection.Emit/MethodBuilder.xml index 83fbe3dd743..a4c18b325be 100644 --- a/xml/System.Reflection.Emit/MethodBuilder.xml +++ b/xml/System.Reflection.Emit/MethodBuilder.xml @@ -56,7 +56,46 @@ Defines and represents a method (or constructor) on a dynamic class. - For more information about this API, see Supplemental API remarks for MethodBuilder. + + class is used to fully describe a method in common intermediate language (CIL), including the name, attributes, signature, and method body. It is used in conjunction with the class to create classes at runtime. + +You can use reflection emit to define global methods and to define methods as type members. The APIs that define methods return objects. + +## Global methods + +A global method is defined by using the method, which returns a `MethodBuilder` object. + +Global methods must be static. If a dynamic module contains global methods, the method must be called before persisting the dynamic module or the containing dynamic assembly because the common language runtime postpones fixing up the dynamic module until all global functions have been defined. + +A global native method is defined by using the method. Platform invoke (PInvoke) methods must not be declared abstract or virtual. The runtime sets the attribute for a platform invoke method. + +## Methods as members of types + +A method is defined as a type member by using the method, which returns a object. + +The method is used to set the name and parameter attributes of a parameter, or of the return value. The object returned by this method represents a parameter or the return value. The object can be used to set the marshaling, to set the constant value, and to apply custom attributes. + +## Attributes + +Members of the enumeration define the precise character of a dynamic method: + +- Static methods are specified using the attribute. +- Final methods (methods that cannot be overridden) are specified using the attribute. +- Virtual methods are specified using the attribute. +- Abstract methods are specified using the attribute. +- Several attributes determine method visibility. See the description of the enumeration. +- Methods that implement overloaded operators must set the attribute. +- Finalizers must set the attribute. + +## Known issues + +- Although is derived from , some of the abstract methods defined in the class are not fully implemented in . These methods throw the . For example the method is not fully implemented. You can reflect on these methods by retrieving the enclosing type using the or methods. +- Custom modifiers are supported. + + ]]> + class to create a method within a dynamic type. diff --git a/xml/System.Reflection.Emit/PersistedAssemblyBuilder.xml b/xml/System.Reflection.Emit/PersistedAssemblyBuilder.xml index 23c5e7a2b04..01059875a0b 100644 --- a/xml/System.Reflection.Emit/PersistedAssemblyBuilder.xml +++ b/xml/System.Reflection.Emit/PersistedAssemblyBuilder.xml @@ -28,8 +28,129 @@ ## Remarks -For more information about this API, see [Persisted dynamic assemblies in .NET](/dotnet/fundamentals/runtime-libraries/system-reflection-emit-persistedassemblybuilder). +The API wasn't originally ported to .NET (Core) because the implementation depended heavily on Windows-specific native code that also wasn't ported. .NET 9 added the class, which provides a fully managed `Reflection.Emit` implementation that supports saving. This implementation has no dependency on the pre-existing, runtime-specific `Reflection.Emit` implementation. That is, now there are two different implementations in .NET: *runnable* and *persisted*. To run the persisted assembly, first save it into a memory stream or a file, then load it back. +Before `PersistedAssemblyBuilder`, you could only run a generated assembly and not save it. Since the assembly was in-memory only, it was difficult to debug. Advantages of saving a dynamic assembly to a file are: + +- You can verify the generated assembly with tools such as ILVerify, or decompile and manually examine it with tools such as ILSpy. +- The saved assembly can be loaded directly, without needing to compile again, which can decrease application startup time. + +To create a `PersistedAssemblyBuilder` instance, use the constructor. The `coreAssembly` parameter is used to resolve base runtime types and can be used for resolving reference assembly versioning: + +- If `Reflection.Emit` is used to generate an assembly that will only be executed on the same runtime version as the runtime version that the compiler is running on (typically in-proc), the core assembly can be simply `typeof(object).Assembly`. The following example demonstrates how to create and save an assembly to a stream and run it with the current runtime assembly: + + :::code language="csharp" source="~/snippets/csharp/System.Reflection.Emit/PersistedAssemblyBuilder/Overview/CreateAndRunAssembly.cs" id="Snippet1"::: + +- If `Reflection.Emit` is used to generate an assembly that targets a specific TFM, open the reference assemblies for the given TFM using `MetadataLoadContext` and use the value of the [MetadataLoadContext.CoreAssembly](xref:System.Reflection.MetadataLoadContext.CoreAssembly) property for `coreAssembly`. This value allows the generator to run on one .NET runtime version and target a different .NET runtime version. You should use types returned by the `MetadataLoadContext` instance when referencing core types. For example, instead of `typeof(int)`, find the `System.Int32` type in `MetadataLoadContext.CoreAssembly` by name: + + :::code language="csharp" source="~/snippets/csharp/System.Reflection.Emit/PersistedAssemblyBuilder/Overview/CreateAndRunAssembly.cs" id="Snippet2"::: + +## Set entry point for an executable + +To set the entry point for an executable or to set other options for the assembly file, you can call the `public MetadataBuilder GenerateMetadata(out BlobBuilder ilStream, out BlobBuilder mappedFieldData)` method and use the populated metadata to generate the assembly with desired options, for example: + +:::code language="csharp" source="~/snippets/csharp/System.Reflection.Emit/PersistedAssemblyBuilder/Overview/GenerateMetadataSnippets.cs" id="Snippet1"::: + +## Emit symbols and generate PDB + +The symbols metadata is populated into the `pdbBuilder` out parameter when you call the method on a `PersistedAssemblyBuilder` instance. To create an assembly with a portable PDB: + +1. Create instances with the method. While emitting the method's IL, also emit the corresponding symbol info. +2. Create a instance using the `pdbBuilder` instance produced by the method. +3. Serialize the `PortablePdbBuilder` into a , and write the `Blob` into a PDB file stream (only if you're generating a standalone PDB). +4. Create a instance and add a (standalone PDB) or . +5. Set the optional `debugDirectoryBuilder` argument when creating the instance. + +The following example shows how to emit symbol info and generate a PDB file. + +```csharp +static void GenerateAssemblyWithPdb() +{ + PersistedAssemblyBuilder ab = new PersistedAssemblyBuilder(new AssemblyName("MyAssembly"), typeof(object).Assembly); + ModuleBuilder mb = ab.DefineDynamicModule("MyModule"); + TypeBuilder tb = mb.DefineType("MyType", TypeAttributes.Public | TypeAttributes.Class); + MethodBuilder mb1 = tb.DefineMethod("SumMethod", MethodAttributes.Public | MethodAttributes.Static, typeof(int), [typeof(int), typeof(int)]); + ISymbolDocumentWriter srcDoc = mb.DefineDocument("MySourceFile.cs", SymLanguageType.CSharp); + ILGenerator il = mb1.GetILGenerator(); + LocalBuilder local = il.DeclareLocal(typeof(int)); + local.SetLocalSymInfo("myLocal"); + il.MarkSequencePoint(srcDoc, 7, 0, 7, 11); + ... + il.Emit(OpCodes.Ret); + + MethodBuilder entryPoint = tb.DefineMethod("Main", MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.Static); + ILGenerator il2 = entryPoint.GetILGenerator(); + il2.BeginScope(); + ... + il2.EndScope(); + ... + tb.CreateType(); + + MetadataBuilder metadataBuilder = ab.GenerateMetadata(out BlobBuilder ilStream, out _, out MetadataBuilder pdbBuilder); + MethodDefinitionHandle entryPointHandle = MetadataTokens.MethodDefinitionHandle(entryPoint.MetadataToken); + DebugDirectoryBuilder debugDirectoryBuilder = GeneratePdb(pdbBuilder, metadataBuilder.GetRowCounts(), entryPointHandle); + + ManagedPEBuilder peBuilder = new ManagedPEBuilder( + header: new PEHeaderBuilder(imageCharacteristics: Characteristics.ExecutableImage, subsystem: Subsystem.WindowsCui), + metadataRootBuilder: new MetadataRootBuilder(metadataBuilder), + ilStream: ilStream, + debugDirectoryBuilder: debugDirectoryBuilder, + entryPoint: entryPointHandle); + + BlobBuilder peBlob = new BlobBuilder(); + peBuilder.Serialize(peBlob); + + using var fileStream = new FileStream("MyAssembly.exe", FileMode.Create, FileAccess.Write); + peBlob.WriteContentTo(fileStream); +} + +static DebugDirectoryBuilder GeneratePdb(MetadataBuilder pdbBuilder, ImmutableArray rowCounts, MethodDefinitionHandle entryPointHandle) +{ + BlobBuilder portablePdbBlob = new BlobBuilder(); + PortablePdbBuilder portablePdbBuilder = new PortablePdbBuilder(pdbBuilder, rowCounts, entryPointHandle); + BlobContentId pdbContentId = portablePdbBuilder.Serialize(portablePdbBlob); + // In case saving PDB to a file + using FileStream fileStream = new FileStream("MyAssemblyEmbeddedSource.pdb", FileMode.Create, FileAccess.Write); + portablePdbBlob.WriteContentTo(fileStream); + + DebugDirectoryBuilder debugDirectoryBuilder = new DebugDirectoryBuilder(); + debugDirectoryBuilder.AddCodeViewEntry("MyAssemblyEmbeddedSource.pdb", pdbContentId, portablePdbBuilder.FormatVersion); + // In case embedded in PE: + // debugDirectoryBuilder.AddEmbeddedPortablePdbEntry(portablePdbBlob, portablePdbBuilder.FormatVersion); + return debugDirectoryBuilder; +} +``` + +Further, you can add by calling the method from the `pdbBuilder` instance to add source embedding and source indexing advanced PDB information. + +```csharp +private static void EmbedSource(MetadataBuilder pdbBuilder) +{ + byte[] sourceBytes = File.ReadAllBytes("MySourceFile2.cs"); + BlobBuilder sourceBlob = new BlobBuilder(); + sourceBlob.WriteBytes(sourceBytes); + pdbBuilder.AddCustomDebugInformation(MetadataTokens.DocumentHandle(1), + pdbBuilder.GetOrAddGuid(new Guid("0E8A571B-6926-466E-B4AD-8AB04611F5FE")), pdbBuilder.GetOrAddBlob(sourceBlob)); +} +``` + +## Add resources with PersistedAssemblyBuilder + +You can call to add as many resources as needed. Streams must be concatenated into one that you pass into the argument. +The following example shows how to create resources and attach it to the assembly that's created. + +:::code language="csharp" source="~/snippets/csharp/System.Reflection.Emit/PersistedAssemblyBuilder/Overview/GenerateMetadataSnippets.cs" id="Snippet2"::: + +The following example shows how to read resources from the created assembly. + +:::code language="csharp" source="~/snippets/csharp/System.Reflection.Emit/PersistedAssemblyBuilder/Overview/GenerateMetadataSnippets.cs" id="Snippet3"::: + +> [!NOTE] +> The metadata tokens for all members are populated on the operation. Don't use the tokens of a generated type and its members before saving, as they'll have default values or throw exceptions. It's safe to use tokens for types that are referenced, not generated. +> +> Some APIs that aren't important for emitting an assembly aren't implemented; for example, `GetCustomAttributes()` is not implemented. With the runtime implementation, you were able to use those APIs after creating the type. For the persisted `AssemblyBuilder`, they throw `NotSupportedException` or `NotImplementedException`. If you have a scenario that requires those APIs, file an issue in the [dotnet/runtime repo](https://github.com/dotnet/runtime). + +For an alternative way to generate assembly files, see . > [!WARNING] > `PersistedAssemblyBuilder` APIs require a fully trusted environment with trusted input, similar to other technologies such as compilers. There are no restrictions other than basic validation for generated IL that the `AssemblyBuilder` can contain. That includes validation for member name, count, and associated metadata, such as custom attributes. ]]> diff --git a/xml/System.Reflection.Emit/TypeBuilder.xml b/xml/System.Reflection.Emit/TypeBuilder.xml index 2facb93c378..c5f2c5fa8ef 100644 --- a/xml/System.Reflection.Emit/TypeBuilder.xml +++ b/xml/System.Reflection.Emit/TypeBuilder.xml @@ -62,7 +62,45 @@ Defines and creates new instances of classes during run time. - For more information about this API, see Supplemental API remarks for TypeBuilder. + + is the root class used to control the creation of dynamic classes in the runtime. It provides a set of routines that are used to define classes, add methods and fields, and create the class inside a module. A new can be created from a dynamic module by calling the method, which returns a object. + +Reflection emit provides the following options for defining types: + +- Define a class or interface with the given name. +- Define a class or interface with the given name and attributes. +- Define a class with the given name, attributes, and base class. +- Define a class with the given name, attributes, base class, and the set of interfaces that the class implements. +- Define a class with the given name, attributes, base class, and packing size. +- Define a class with the given name, attributes, base class, and the class size as a whole. +- Define a class with the given name, attributes, base class, packing size, and the class size as a whole. + +To create an array type, pointer type, or byref type for an incomplete type that is represented by a object, use the method, method, or method, respectively. + +Before a type is used, the method must be called. **CreateType** completes the creation of the type. Following the call to **CreateType**, the caller can instantiate the type by using the method, and invoke members of the type by using the method. It is an error to invoke methods that change the implementation of a type after **CreateType** has been called. For example, the common language runtime throws an exception if the caller tries to add new members to a type. + +A class initializer is created by using the method. **DefineTypeInitializer** returns a object. + +Nested types are defined by calling one of the methods. + +## Attributes + +The class uses the enumeration to further specify the characteristics of the type to be created: + +- Interfaces are specified using the and attributes. +- Concrete classes (classes that cannot be extended) are specified using the attribute. +- Several attributes determine type visibility. See the description of the enumeration. +- If is specified, the class loader lays out fields in the order they are read from metadata. The class loader considers the specified packing size but ignores any specified field offsets. The metadata preserves the order in which the field definitions are emitted. Even across a merge, the metadata will not reorder the field definitions. The loader will honor the specified field offsets only if is specified. + +## Known issues + +- Reflection emit does not verify whether a non-abstract class that implements an interface has implemented all the methods declared in the interface. However, if the class does not implement all the methods declared in an interface, the runtime does not load the class. +- Although is derived from , some of the abstract methods defined in the class are not fully implemented in the class. Calls to these methods throw a exception. The desired functionality can be obtained by retrieving the created type using the or and reflecting on the retrieved type. + + ]]> + An enumeration that describes the format of the debugging information of a . - For more information about this API, see Supplemental API remarks for DebugDirectoryEntryType. + + enum describes the format of the debugging information of a . + +See the following for the specifications related to individual enumeration members: + +|Member|Specification| +|---|---| +|`CodeView`|[CodeView Debug Directory Entry (type 2)](https://github.com/dotnet/runtime/blob/main/docs/design/specs/PE-COFF.md#codeview-debug-directory-entry-type-2)| +|`EmbeddedPortablePdb`|[Embedded Portable PDB Debug Directory Entry (type 17)](https://github.com/dotnet/runtime/blob/main/docs/design/specs/PE-COFF.md#embedded-portable-pdb-debug-directory-entry-type-17)| +|`PdbChecksum`|[PDB Checksum Debug Directory Entry (type 19)](https://github.com/dotnet/runtime/blob/main/docs/design/specs/PE-COFF.md#pdb-checksum-debug-directory-entry-type-19)| +|`Reproducible`|See [Deterministic Debug Directory Entry (type 16)](https://github.com/dotnet/runtime/blob/main/docs/design/specs/PE-COFF.md#deterministic-debug-directory-entry-type-16)| + +## DebugDirectoryEntryType.Reproducible + +The tool that produced the deterministic PE/COFF file guarantees that the entire content of the file is based solely on documented inputs given to the tool (such as source files, resource files, compiler options, etc.) rather than ambient environment variables (such as the current time, the operating system, the bitness of the process running the tool, etc.). + +The value of the `TimeDateStamp` field in the COFF File Header of a deterministic PE/COFF file does not indicate the date and time when the file was produced and should not be interpreted that way. Instead, the value of the field is derived from a hash of the file content. The algorithm to calculate this value is an implementation detail of the tool that produced the file. + +The debug directory entry of type must have all fields except for zeroed. + + ]]> + diff --git a/xml/System.Resources/MissingManifestResourceException.xml b/xml/System.Resources/MissingManifestResourceException.xml index 350ee1599c7..ab28e708cf5 100644 --- a/xml/System.Resources/MissingManifestResourceException.xml +++ b/xml/System.Resources/MissingManifestResourceException.xml @@ -72,7 +72,49 @@ The exception that is thrown if the main assembly does not contain the resources for the neutral culture, and an appropriate satellite assembly is missing. - For more information about this API, see Supplemental API remarks for MissingManifestResourceException. + + exception is thrown for different reasons in .NET versus UWP apps. + +## .NET apps + +In .NET apps, is thrown when the attempt to retrieve a resource fails because the resource set for the neutral culture could not be loaded from a particular assembly. Although the exception is thrown when you try to retrieve a particular resource, it is caused by the failure to load the resource set rather than the failure to find the resource. + +> [!NOTE] +> For additional information, see the "Handling a MissingManifestResourceException Exception" section in the class topic. + +The main causes of the exception include the following: + +- The resource set is not identified by its fully qualified name. For example, if the `baseName` parameter in the call to the method specifies the root name of the resource set without a namespace, but the resource set is assigned a namespace when it is stored in its assembly, the call to the method throws this exception. + + If you've embedded the .resources file that contains the default culture's resources in your executable and your app is throwing a , you can use a reflection tool such as the [IL Disassembler (Ildasm.exe)](/dotnet/framework/tools/ildasm-exe-il-disassembler) to determine the fully qualified name of the resource. In ILDasm, double click the executable's **MANIFEST** label to open the **MANIFEST** window. Resources appear as `.mresource` items and are listed after external assembly references and custom assembly-level attributes. You can also compile the following simple utility, which lists the fully qualified names of embedded resources in the assembly whose name is passed to it as a command-line parameter. + + :::code language="csharp" source="~/snippets/csharp/System.Resources/MissingManifestResourceException/Overview/resourcenames.cs" id="Snippet4"::: + :::code language="vb" source="~/snippets/visualbasic/System.Resources/MissingManifestResourceException/Overview/resourcenames.vb" id="Snippet4"::: + +- You identify the resource set by its resource file name (along with its optional namespace) and its file extension rather than by its namespace and root file name alone. For example, this exception is thrown if the neutral culture's resource set is named `GlobalResources` and you supply a value of `GlobalResources.resources` (instead of `GlobalResources`) to the `baseName` parameter of the constructor. + +- The culture-specific resource set that is identified in a method call cannot be found, and the fallback resource set cannot be loaded. For example, if you create satellite assemblies for the English (United States) and Russia (Russian) cultures but you fail to provide a resource set for the neutral culture, this exception is thrown if your app's current culture is English (United Kingdom). + + uses the HRESULT `COR_E_MISSINGMANIFESTRESOURCE`, which has the value 0x80131532. + + uses the default implementation, which supports reference equality. + +For a list of initial property values for an instance of , see the constructors. + +> [!NOTE] +> We recommend that you include a neutral set of resources in your main assembly, so your app won't fail if a satellite assembly is unavailable. + +## Universal Windows Platform (UWP) apps + +UWP apps deploy resources for multiple cultures, including the neutral culture, in a single package resource index (.pri) file. As a result, in a UWP app, if resources for the preferred culture cannot be found, the is thrown under either of the following conditions: + +- The app does not include a .pri file, or the .pri file could not be opened. +- The app's .pri file does not contain a resource set for the given root name. + + ]]> + Handling and throwing exceptions in .NET diff --git a/xml/System.Resources/NeutralResourcesLanguageAttribute.xml b/xml/System.Resources/NeutralResourcesLanguageAttribute.xml index 9a407e571c1..c97775cd0fe 100644 --- a/xml/System.Resources/NeutralResourcesLanguageAttribute.xml +++ b/xml/System.Resources/NeutralResourcesLanguageAttribute.xml @@ -70,7 +70,112 @@ Informs the resource manager of an app's default culture. This class cannot be inherited. - For more information about this API, see Supplemental API remarks for NeutralResourcesLanguageAttribute. + + attribute informs the resource manager of an app's default culture and the location of its resources. By default, resources are embedded in the main app assembly, and you can use the attribute as follows. This statement specifies that the English (United States) is the app's default culture. + +```csharp +[assembly: NeutralResourcesLanguage("en-US")] +``` + +```vb + +``` + +You can also use the attribute to indicate where can find the resources of the default culture by providing an enumeration value in the attribute statement. This is most commonly done to indicate that the resources reside in a satellite assembly. For example, the following statement specifies that English (United States) is the app's default or neutral culture and that its resources reside in a satellite assembly. The object will look for them in a subdirectory named en-US. + +```csharp +[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] +``` + +```vb + +``` + +> [!TIP] +> We recommend that you always use the attribute to define the default culture of your app. + +The attribute performs two roles: + +- If the default culture's resources are embedded in the app's main assembly and has to retrieve resources that belong to the same culture as the default culture, the automatically uses the resources located in the main assembly instead of searching for a satellite assembly. This bypasses the usual assembly probe, improves lookup performance for the first resource you load, and can reduce your working set. See [Packaging and Deploying Resources](/dotnet/framework/resources/packaging-and-deploying-resources-in-desktop-apps) for the process uses to probe for resource files. + +- If the default culture's resources are located in a satellite assembly rather than in the main app assembly, the attribute specifies the culture and the directory from which the runtime can load the resources. + +## Examples + +The following example uses a simple "Hello World" app to illustrate the use of the attribute to define a default or fallback culture. It requires the creation of separate resource files for the English (en), English (United States) (en-US), and French (France) (fr-FR) cultures. The following shows the contents of a text file named ExampleResources.txt for the English culture. + +``` +# Resources for the default (en) culture. +Greeting=Hello +``` + +To use the resource file in an app, you must use the [Resource File Generator (Resgen.exe)](/dotnet/framework/tools/resgen-exe-resource-file-generator) to convert the file from its text (.txt) format to a binary (.resources) format as follows: + +``` +resgen ExampleResources.txt +``` + +When the app is compiled, the binary resource file will be embedded in the main app assembly. + +The following shows the contents of a text file named ExampleResources.en-US.txt that provides resources for the English (United States) culture. + +``` +# Resources for the en-US culture. +Greeting=Hi +``` + +The text file can be converted to a binary resources file by using the [Resource File Generator (ResGen.exe)](/dotnet/framework/tools/resgen-exe-resource-file-generator) at the command line as follows: + +``` +resgen ExampleResources.en-US.txt ExampleResources.en-US.resources +``` + +The binary resource file should then be compiled into an assembly by using [Assembly Linker (Al.exe)](/dotnet/framework/tools/al-exe-assembly-linker) and placed in the en-US subdirectory of the app directory by issuing the following command: + +``` +al /t:lib /embed:ExampleResources.en-US.resources /culture:en-US /out:en-us\Example.resources.dll +``` + +The following shows the contents of a text file named ExampleResources.fr-FR.txt that provides resources for the French (France) culture. + +``` +# Resources for the fr-FR culture. +Greeting=Bonjour +``` + +The text file can be converted to a binary resource file by using ResGen.exe at the command line as follows: + +``` +resgen ExampleResources.fr-FR.txt ExampleResources.fr-FR.resources +``` + +The binary resources file should then be compiled into an assembly by using Assembly Linker and placed in the fr-FR subdirectory of the app directory by issuing the following command: + +``` +al /t:lib /embed:ExampleResources.fr-FR.resources /culture:fr-FR /out:fr-FR\Example.resources.dll +``` + +The following example provides the executable code that sets the current culture, prompts for the user's name, and displays a localized string. + +:::code language="csharp" source="~/snippets/csharp/System.Resources/NeutralResourcesLanguageAttribute/Overview/example.cs" id="Snippet1"::: +:::code language="vb" source="~/snippets/visualbasic/System.Resources/NeutralResourcesLanguageAttribute/Overview/example.vb" id="Snippet1"::: + +It can be compiled by using the following command in Visual Basic: + +``` +vbc Example.vb /resource:ExampleResources.resources +``` + +or by using the following command in C#: + +``` +csc Example.cs /resource:ExampleResources.resources +``` + + ]]> + Packaging and Deploying Resources diff --git a/xml/System.Resources/ResourceManager.xml b/xml/System.Resources/ResourceManager.xml index 6db9fd8f96d..b9265c01a15 100644 --- a/xml/System.Resources/ResourceManager.xml +++ b/xml/System.Resources/ResourceManager.xml @@ -66,7 +66,255 @@ Represents a resource manager that provides convenient access to culture-specific resources at run time. - For more information about this API, see Supplemental API remarks for ResourceManager. + + class retrieves resources from a binary .resources file that is embedded in an assembly or from a standalone .resources file. If an app has been localized and localized resources have been deployed in [satellite assemblies](/dotnet/framework/resources/creating-satellite-assemblies-for-desktop-apps), it looks up culture-specific resources, provides resource fallback when a localized resource does not exist, and supports resource serialization. + +## Desktop apps + +For desktop apps, the class retrieves resources from binary resource (.resources) files. Typically, a language compiler or the [Assembly Linker (AL.exe)](/dotnet/framework/tools/al-exe-assembly-linker) embeds these resource files in an assembly. You can also use a object to retrieve resources directly from a .resources file that is not embedded in an assembly, by calling the method. + +> [!CAUTION] +> Using standalone .resources files in an ASP.NET app will break XCOPY deployment, because the resources remain locked until they are explicitly released by the method. If you want to deploy resources with your ASP.NET apps, you should compile your .resources files into satellite assemblies. + +In a resource-based app, one .resources file contains the resources of the default culture whose resources are used if no culture-specific resources can be found. For example, if an app's default culture is English (en), the English language resources are used whenever localized resources cannot be found for a specific culture, such as English (United States) (en-US) or French (France) (fr-FR). Typically, the resources for the default culture are embedded in the main app assembly, and resources for other localized cultures are embedded in satellite assemblies. Satellite assemblies contain only resources. They have the same root file name as the main assembly and an extension of .resources.dll. For apps whose assemblies are not registered in the global assembly cache, satellite assemblies are stored in an app subdirectory whose name corresponds to the assembly's culture. + +### Create resources + +When you develop a resource-based app, you store resource information in text files (files that have a .txt or .restext extension) or XML files (files that have a .resx extension). You then compile the text or XML files with the [Resource File Generator (Resgen.exe)](/dotnet/framework/tools/resgen-exe-resource-file-generator) to create a binary .resources file. You can then embed the resulting .resources file in an executable or library by using a compiler option such as `/resources` for the C# and Visual Basic compilers, or you can embed it in a satellite assembly by using the [Assembly Linker (AL.exe)](/dotnet/framework/tools/al-exe-assembly-linker). If you include a .resx file in your Visual Studio project, Visual Studio handles the compilation and embedding of default and localized resources automatically as part of the build process. + +Ideally, you should create resources for every language your app supports, or at least for a meaningful subset of each language. The binary .resources file names follow the naming convention *basename*.*cultureName*.resources, where *basename* is the name of the app or the name of a class, depending on the level of detail you want. The property is used to determine *cultureName*. A resource for the app's default culture should be named *basename*.resources. + +For example, suppose that an assembly has several resources in a resource file that has the base name MyResources. These resource files should have names such as MyResources.ja-JP.resources for the Japan (Japanese) culture, MyResources.de.resources for the German culture, MyResources.zh-CHS.resources for the simplified Chinese culture, and MyResources.fr-BE.resources for the French (Belgium) culture. The default resource file should be named MyResources.resources. The culture-specific resource files are commonly packaged in satellite assemblies for each culture. The default resource file should be embedded in the app's main assembly. + +Note that [Assembly Linker](/dotnet/framework/tools/al-exe-assembly-linker) allows resources to be marked as private, but you should always mark them as public so they can be accessed by other assemblies. (Because a satellite assembly contains no code, resources that are marked as private are unavailable to your app through any mechanism.) + +For more information about creating, packaging, and deploying resources, see the articles [Creating Resource Files](/dotnet/framework/resources/creating-resource-files-for-desktop-apps), [Creating Satellite Assemblies](/dotnet/framework/resources/creating-satellite-assemblies-for-desktop-apps), and [Packaging and Deploying Resources](/dotnet/framework/resources/packaging-and-deploying-resources-in-desktop-apps). + +### Instantiate a ResourceManager object + +You instantiate a object that retrieves resources from an embedded .resources file by calling one of its class constructor overloads. This tightly couples a object with a particular .resources file and with any associated localized .resources files in satellite assemblies. + +The two most commonly called constructors are: + +- looks up resources based on two pieces of information that you supply: the base name of the .resources file, and the assembly in which the default .resources file resides. The base name includes the namespace and root name of the .resources file, without its culture or extension. Note that .resources files that are compiled from the command line typically do not include a namespace name, whereas .resources files that are created in the Visual Studio environment do. For example, if a resource file is named MyCompany.StringResources.resources and the constructor is called from a static method named `Example.Main`, the following code instantiates a object that can retrieve resources from the .resources file: + + :::code language="csharp" source="~/snippets/csharp/System.Resources/ResourceManager/Overview/ctor1.cs" id="Snippet1"::: + :::code language="vb" source="~/snippets/visualbasic/System.Resources/ResourceManager/Overview/ctor1.vb" id="Snippet1"::: + +- looks up resources in satellite assemblies based on information from a type object. The type's fully qualified name corresponds to the base name of the .resources file without its file name extension. In desktop apps that are created by using the Visual Studio Resource Designer, Visual Studio creates a wrapper class whose fully qualified name is the same as the root name of the .resources file. For example, if a resource file is named MyCompany.StringResources.resources and there is a wrapper class named `MyCompany.StringResources`, the following code instantiates a object that can retrieve resources from the .resources file: + + :::code language="csharp" source="~/snippets/csharp/System.Resources/ResourceManager/Overview/ctor1.cs" id="Snippet2"::: + :::code language="vb" source="~/snippets/visualbasic/System.Resources/ResourceManager/Overview/ctor1.vb" id="Snippet2"::: + +If the appropriate resources cannot be found, the constructor call creates a valid object. However, the attempt to retrieve a resource throws a exception. For information about dealing with the exception, see the [Handle MissingManifestResourceException and MissingSatelliteAssemblyException Exceptions](#handle-missingmanifestresourceexception-and-missingsatelliteassemblyexception-exceptions) section later in this article. + +The following example shows how to instantiate a object. It contains the source code for an executable named ShowTime.exe. It also includes the following text file named Strings.txt that contains a single string resource, `TimeHeader`: + +``` +TimeHeader=The current time is +``` + +You can use a batch file to generate the resource file and embed it into the executable. Here's the batch file to generate an executable by using the C# compiler: + +``` +resgen strings.txt +csc ShowTime.cs /resource:strings.resources +``` + +For the Visual Basic compiler, you can use the following batch file: + +``` +resgen strings.txt +vbc ShowTime.vb /resource:strings.resources +``` + +:::code language="csharp" source="~/snippets/csharp/System.Resources/MissingManifestResourceException/Overview/showtime.cs" id="Snippet1"::: +:::code language="vb" source="~/snippets/visualbasic/System.Resources/ResourceManager/Overview/showtime.vb" id="Snippet1"::: + +### ResourceManager and culture-specific resources + +A localized app requires resources to be deployed, as discussed in the article [Packaging and Deploying Resources](/dotnet/framework/resources/packaging-and-deploying-resources-in-desktop-apps). If the assemblies are properly configured, the resource manager determines which resources to retrieve based on the current thread's property. (That property also returns the current thread's UI culture.) For example, if an app is compiled with default English language resources in the main assembly and with French and Russian language resources in two satellite assemblies, and the property is set to fr-FR, the resource manager retrieves the French resources. + +You can set the property explicitly or implicitly. The way you set it determines how the object retrieves resources based on culture: + +- If you explicitly set the property to a specific culture, the resource manager always retrieves the resources for that culture, regardless of the user's browser or operating system language. Consider an app that is compiled with default English language resources and three satellite assemblies that contain resources for English (United States), French (France), and Russian (Russia). If the property is set to fr-FR, the object always retrieves the French (France) resources, even if the user's operating system language is not French. Make sure that this is the desired behavior before you set the property explicitly. + + In ASP.NET apps, you must set the property explicitly, because it is unlikely that the setting on the server will match incoming client requests. An ASP.NET app can set the property explicitly to the user's browser accept language. + + Explicitly setting the property defines the current UI culture for that thread. It does not affect the current UI culture of any other threads in an app. + +- You can set the UI culture of all threads in an app domain by assigning a object that represents that culture to the static property. + +- If you do not explicitly set the current UI culture and you do not define a default culture for the current app domain, the property is set implicitly by the Windows `GetUserDefaultUILanguage` function. This function is provided by the Multilingual User Interface (MUI), which enables the user to set the default language. If the UI language is not set by the user, it defaults to the system-installed language, which is the language of operating system resources. + +The following simple "Hello world" example sets the current UI culture explicitly. It contains resources for three cultures: English (United States) or en-US, French (France) or fr-FR, and Russian (Russia) or ru-RU. The en-US resources are contained in a text file named Greetings.txt: + +``` +HelloString=Hello world! +``` + +The fr-FR resources are contained in a text file named Greetings.fr-FR.txt: + +``` +HelloString=Salut tout le monde! +``` + +The ru-RU resources are contained in a text file named Greetings.ru-RU.txt: + +``` +HelloString=Всем привет! +``` + +Here's the source code for the example (Example.vb for the Visual Basic version or Example.cs for the C# version): + +:::code language="csharp" source="~/snippets/csharp/System.Resources/ResourceManager/Overview/example.cs" id="Snippet1"::: +:::code language="vb" source="~/snippets/visualbasic/System.Resources/CurrentCulture/Overview/example.vb" id="Snippet1"::: + +To compile this example, create a batch (.bat) file that contains the following commands and run it from the command prompt. If you're using C#, specify `csc` instead of `vbc` and `Example.cs` instead of `Example.vb`. + +``` +resgen Greetings.txt +vbc Example.vb /resource:Greetings.resources + +resgen Greetings.fr-FR.txt +Md fr-FR +al /embed:Greetings.fr-FR.resources /culture:fr-FR /out:fr-FR\Example.resources.dll + +resgen Greetings.ru-RU.txt +Md ru-RU +al /embed:Greetings.ru-RU.resources /culture:ru-RU /out:ru-RU\Example.resources.dll +``` + +### Retrieve resources + +You call the and methods to access a specific resource. You can also call the method to retrieve non-string resources as a byte array. By default, in an app that has localized resources, these methods return the resource for the culture determined by the current UI culture of the thread that made the call. See the previous section, [ResourceManager and culture-specific resources](#resourcemanager-and-culture-specific-resources), for more information about how the current UI culture of a thread is defined. If the resource manager cannot find the resource for the current thread's UI culture, it uses a fallback process to retrieve the specified resource. If the resource manager cannot find any localized resources, it uses the resources of the default culture. For more information about resource fallback rules, see the "Resource Fallback Process" section of the article [Packaging and Deploying Resources](/dotnet/framework/resources/packaging-and-deploying-resources-in-desktop-apps). + +> [!NOTE] +> If the .resources file specified in the class constructor cannot be found, the attempt to retrieve a resource throws a or exception. For information about dealing with the exception, see the [Handle MissingManifestResourceException and MissingSatelliteAssemblyException Exceptions](#handle-missingmanifestresourceexception-and-missingsatelliteassemblyexception-exceptions) section later in this article. + +The following example uses the method to retrieve culture-specific resources. It consists of resources compiled from .txt files for the English (en), French (France) (fr-FR), and Russian (Russia) (ru-RU) cultures. The example changes the current culture and current UI culture to English (United States), French (France), Russian (Russia), and Swedish (Sweden). It then calls the method to retrieve the localized string, which it displays along with the current day and month. Notice that the output displays the appropriate localized string except when the current UI culture is Swedish (Sweden). Because Swedish language resources are unavailable, the app instead uses the resources of the default culture, which is English. + +The example requires the text-based resource files listed in following table. Each has a single string resource named `DateStart`. + +| Culture | File name | Resource name | Resource value | +|---------|-----------------------|---------------|-----------------------| +| en-US | DateStrings.txt | `DateStart` | Today is | +| fr-FR | DateStrings.fr-FR.txt | `DateStart` | Aujourd'hui, c'est le | +| ru-RU | DateStrings.ru-RU.txt | `DateStart` | Сегодня | + +Here's the source code for the example (ShowDate.vb for the Visual Basic version or ShowDate.cs for the C# version of the code). + +:::code language="csharp" source="~/snippets/csharp/System.Resources/MissingManifestResourceException/Overview/showdate.cs" id="Snippet2"::: +:::code language="vb" source="~/snippets/visualbasic/System.Resources/ResourceManager/Overview/showdate.vb" id="Snippet2"::: + +To compile this example, create a batch file that contains the following commands and run it from the command prompt. If you're using C#, specify `csc` instead of `vbc` and `showdate.cs` instead of `showdate.vb`. + +``` +resgen DateStrings.txt +vbc showdate.vb /resource:DateStrings.resources + +md fr-FR +resgen DateStrings.fr-FR.txt +al /out:fr-FR\Showdate.resources.dll /culture:fr-FR /embed:DateStrings.fr-FR.resources + +md ru-RU +resgen DateStrings.ru-RU.txt +al /out:ru-RU\Showdate.resources.dll /culture:ru-RU /embed:DateStrings.ru-RU.resources +``` + +There are two ways to retrieve the resources of a specific culture other than the current UI culture: + +- You can call the , , or method to retrieve a resource for a specific culture. If a localized resource cannot be found, the resource manager uses the resource fallback process to locate an appropriate resource. +- You can call the method to obtain a object that represents the resources for a particular culture. In the method call, you can determine whether the resource manager probes for parent cultures if it is unable to find localized resources, or whether it simply falls back to the resources of the default culture. You can then use the methods to access the resources (localized for that culture) by name, or to enumerate the resources in the set. + +### Handle MissingManifestResourceException and MissingSatelliteAssemblyException exceptions + +If you try to retrieve a specific resource, but the resource manager cannot find that resource and either no default culture has been defined or the resources of the default culture cannot be located, the resource manager throws a exception if it expects to find the resources in the main assembly or a if it expects to find the resources in a satellite assembly. Note that the exception is thrown when you call a resource retrieval method such as or , and not when you instantiate a object. + +The exception is typically thrown under the following conditions: + +- The appropriate resource file or satellite assembly does not exist. If the resource manager expects the app's default resources to be embedded in the main app assembly, they are absent. If the attribute indicates that the app's default resources reside in a satellite assembly, that assembly cannot be found. When you compile your app, make sure that resources are embedded in the main assembly or that the necessary satellite assembly is generated and is named appropriately. Its name should take the form *appName*.resources.dll, and it should be located in a directory named after the culture whose resources it contains. + +- Your app doesn't have a default or neutral culture defined. Add the attribute to a source code file or to the project information file (AssemblyInfo.vb for a Visual Basic app or AssemblyInfo.cs for a C# app) file. + +- The `baseName` parameter in the constructor does not specify the name of a .resources file. The name should include the resource file's fully qualified namespace but not its file name extension. Typically, resource files that are created in Visual Studio include namespace names, but resource files that are created and compiled at the command prompt do not. You can determine the names of embedded .resources files by compiling and running the following utility. This is a console app that accepts the name of a main assembly or satellite assembly as a command-line parameter. It displays the strings that should be provided as the `baseName` parameter so that the resource manager can correctly identify the resource. + + :::code language="csharp" source="~/snippets/csharp/System.Resources/MissingManifestResourceException/Overview/resourcenames.cs" id="Snippet4"::: + :::code language="vb" source="~/snippets/visualbasic/System.Resources/MissingManifestResourceException/Overview/resourcenames.vb" id="Snippet4"::: + +If you are changing the current culture of your application explicitly, you should also remember that the resource manager retrieves a resource set based on the value of the property, and not the property. Typically, if you change one value, you should also change the other. + +### Resource versioning + +Because the main assembly that contains an app's default resources is separate from the app's satellite assemblies, you can release a new version of your main assembly without redeploying the satellite assemblies. The attribute instructs the resource manager to use existing satellite assemblies and not to redeploy them with a new version of your main assembly. + +For more information about versioning support for satellite assemblies, see the article [Retrieving Resources](/dotnet/framework/resources/retrieving-resources-in-desktop-apps). + +## Examples + +The following example demonstrates how to use an explicit culture and the implicit current UI culture to obtain string resources from a main assembly and a satellite assembly. For more information, see the "Directory Locations for Satellite Assemblies Not Installed in the Global Assembly Cache" section of the [Creating Satellite Assemblies](/dotnet/framework/resources/creating-satellite-assemblies-for-desktop-apps) topic. + +To run this example: + +1. In the app directory, create a file named rmc.txt that contains the following resource strings: + + ``` + day=Friday + year=2006 + holiday="Cinco de Mayo" + ``` + +2. Use the [Resource File Generator](/dotnet/framework/tools/resgen-exe-resource-file-generator) to generate the rmc.resources resource file from the rmc.txt input file as follows: + + ``` + resgen rmc.txt + ``` + +3. Create a subdirectory of the app directory and name it "es-MX". This is the culture name of the satellite assembly that you will create in the next three steps. + +4. Create a file named rmc.es-MX.txt in the es-MX directory that contains the following resource strings: + + ``` + day=Viernes + year=2006 + holiday="Cinco de Mayo" + ``` + +5. Use the [Resource File Generator](/dotnet/framework/tools/resgen-exe-resource-file-generator) to generate the rmc.es-MX.resources resource file from the rmc.es-MX.txt input file as follows: + + ``` + resgen rmc.es-MX.txt + ``` + +6. Assume that the filename for this example is rmc.vb or rmc.cs. Copy the following source code into a file. Then compile it and embed the main assembly resource file, rmc.resources, in the executable assembly. If you are using the Visual Basic compiler, the syntax is: + + ``` + vbc rmc.vb /resource:rmc.resources + ``` + + The corresponding syntax for the C# compiler is: + + ``` + csc /resource:rmc.resources rmc.cs + ``` + +7. Use the [Assembly Linker](/dotnet/framework/tools/al-exe-assembly-linker) to create a satellite assembly. If the base name of the app is rmc, the satellite assembly name must be rmc.resources.dll. The satellite assembly should be created in the es-MX directory. If es-MX is the current directory, use this command: + + ``` + al /embed:rmc.es-MX.resources /c:es-MX /out:rmc.resources.dll + ``` + +8. Run rmc.exe to obtain and display the embedded resource strings. + + :::code language="csharp" source="~/snippets/csharp/System.Resources/ResourceManager/Overview/rmc.cs" id="Snippet1"::: + :::code language="vb" source="~/snippets/visualbasic/System.Resources/ResourceManager/Overview/rmc.vb" id="Snippet1"::: + + ]]> + This type is thread safe. @@ -175,7 +423,69 @@ A type from which the resource manager derives all information for finding .resources files. Initializes a new instance of the class that looks up resources in satellite assemblies based on information from the specified type object. - For more information about this API, see Supplemental API remarks for ResourceManager constructor. + + attribute is not used to indicate that the resources of the default culture reside in a satellite assembly, the resource manager assumes that the resource file for the default culture is found in the same assembly as the type specified by the `resourceSource` parameter. +- The resource manager assumes that the default resource file has the same base name as the type specified by the `resourceSource` parameter. +- The resource manager uses the default class to manipulate the resource file. + +For example, given a type named `MyCompany.MyProduct.MyType`, the resource manager looks for a *.resources* file named *MyCompany.MyProduct.MyType.resources* in the assembly that defines `MyType`. + +In Visual Studio, the Resource Designer automatically generates code that defines an `internal` (in C#) or `Friend` (in Visual Basic) class whose name is the same as the base name of the *.resources* file for the default culture. This makes it possible to instantiate a object and couple it with a particular set of resources by getting a type object whose name corresponds to the name of the resource, because as long as the class is visible to the compiler, the resources must be as well. For example, if a *.resources* file is named Resource1, the following statement instantiates a object to manage the *.resources* file named Resource1: + +:::code language="csharp" source="~/snippets/csharp/System.Resources/ResourceManager/.ctor/ctor1.cs" id="Snippet2"::: + +If you're not using Visual Studio, you can create a class with no members whose namespace and name are the same as that of the default *.resources* file. The example provides an illustration. + +### Example + +The following example uses the constructor to instantiate a object. It consists of resources compiled from .txt files for the English (en), French (France) (fr-FR), and Russian (Russia) (ru-RU) cultures. The example changes the current culture and current UI culture to English (United States), French (France), Russian (Russia), and Swedish (Sweden). It then calls the method to retrieve the localized string, which displays a greeting that depends on the time of day. + +The example requires three text-based resource files, as listed in the following table. Each file includes string resources named `Morning`, `Afternoon`, and `Evening`. + +| Culture | File name | Resource name | Resource value | +|---------|-----------------------------|---------------|----------------| +| en-US | GreetingResources.txt | `Morning` | Good morning | +| en-US | GreetingResources.txt | `Afternoon` | Good afternoon | +| en-US | GreetingResources.txt | `Evening` | Good evening | +| fr-FR | GreetingResources.fr-FR.txt | `Morning` | Bonjour | +| fr-FR | GreetingResources.fr-FR.txt | `Afternoon` | Bonjour | +| fr-FR | GreetingResources.fr-FR.txt | `Evening` | Bonsoir | +| ru-RU | GreetingResources.ru-RU.txt | `Morning` | Доброе утро | +| ru-RU | GreetingResources.ru-RU.txt | `Afternoon` | Добрый день | +| ru-RU | GreetingResources.ru-RU.txt | `Evening` | Добрый вечер | + +You can use the following batch file to compile the Visual Basic example and create an executable named Greet.exe. To compile with C#, change the compiler name from `vbc` to `csc` and the file extension from `.vb` to `.cs`. + +``` +resgen GreetingResources.txt +vbc Greet.vb /resource: GreetingResources.resources + +md fr-FR +resgen GreetingResources.fr-FR.txt +al /out:fr-FR\Greet.resources.dll /culture:fr-FR /embed: GreetingResources.fr-FR.resources + +md ru-RU +resgen GreetingResources.ru-RU.txt +al /out:ru-RU\Greet.resources.dll /culture:ru-RU /embed: GreetingResources.ru-RU.resources +``` + +Here's the source code for the example (ShowDate.vb for the Visual Basic version or ShowDate.cs for the C# version of the code). + +:::code language="csharp" source="~/snippets/csharp/System.Resources/ResourceManager/.ctor/greet.cs" id="Snippet3"::: +:::code language="vb" source="~/snippets/visualbasic/System.Resources/ResourceManager/.ctor/greet.vb" id="Snippet3"::: + +In addition to defining an app class named `Example`, the source code defines an internal class whose name, `GreetingResources`, is the same as the base name of the resource files. This makes it possible to successfully instantiate a object by calling the constructor. + +Notice that the output displays the appropriate localized string except when the current UI culture is Swedish (Sweden), in which case it uses English language resources. Because Swedish language resources are unavailable, the app uses the resources of the default culture, as defined by the attribute, instead. + + ]]> + The parameter is . @@ -224,7 +534,43 @@ The root name of the resource file without its extension but including any fully qualified namespace name. For example, the root name for the resource file named MyApplication.MyResource.en-US.resources is MyApplication.MyResource. The main assembly for the resources. Initializes a new instance of the class that looks up resources contained in files with the specified root name in the given assembly. - For more information about this API, see Supplemental API remarks for ResourceManager constructor. + + [!NOTE] +> To retrieve resources from *.resources* files directly instead of retrieving them from assemblies, you must call the method instead to instantiate a object. + +If the resource file identified by `baseName` cannot be found in `assembly`, the method instantiates a object, but the attempt to retrieve a specific resource throws an exception, typically . For information about diagnosing the cause of the exception, see the "Handling the MissingManifestResourceException Exception" section of the class topic. + +### Example + +The following example uses a simple non-localized "Hello World" app to illustrate the constructor. The contents of a text file named *ExampleResources.txt* is `Greeting=Hello`. When the app is compiled, the resource is embedded in the main app assembly. + +The text file can be converted to a binary resource file by using the [Resource File Generator (ResGen.exe)](/dotnet/framework/tools/resgen-exe-resource-file-generator) at the command prompt as follows: + +```cmd +resgen ExampleResources.txt +``` + +The following example provides the executable code that instantiates a object, prompts the user to enter a name, and displays a greeting. + +:::code language="csharp" source="~/snippets/csharp/System.Resources/ResourceManager/.ctor/example.cs" id="Snippet1"::: +:::code language="vb" source="~/snippets/visualbasic/System.Resources/ResourceManager/.ctor/example.vb" id="Snippet1"::: + +It can be compiled by using the following command in C#: + +```cmd +csc Example.cs /resource:ExampleResources.resources +``` + +The example retrieves a reference to the assembly that contains the resource file by passing a type defined in that assembly to the `typeof` function (in C#) or the `GetType` function (in Visual Basic) and retrieving the value of its property. + + ]]> + The or parameter is . This constructor uses the system-provided implementation. To use a custom resource file format, you should derive from the class, override the and methods, and pass that type to the constructor. Using a custom can be useful for controlling resource caching policy or supporting your own resource file format, but is generally not necessary. @@ -293,15 +639,16 @@ [!NOTE] -> To retrieve resources from .resources files directly instead of retrieving them from assemblies, you must call the method instead to instantiate a object. +> To retrieve resources from .resources files directly instead of retrieving them from assemblies, you must call the method instead to instantiate a object. - If the resource file identified by `baseName` cannot be found in `assembly`, the method instantiates a object, but the attempt to retrieve a specific resource throws an exception, typically . For information about diagnosing the cause of the exception, see the "Handling the MissingManifestResourceException Exception" section of the class topic. +If the resource file identified by `baseName` cannot be found in `assembly`, the method instantiates a object, but the attempt to retrieve a specific resource throws an exception, typically . For information about diagnosing the cause of the exception, see the "Handling the MissingManifestResourceException Exception" section of the class topic. > [!NOTE] -> The `usingResourceSet` parameter is used to support your own resource format, and will commonly be `null`. This is different from the constructor that takes a only. +> The `usingResourceSet` parameter is used to support your own resource format, and will commonly be `null`. This is different from the constructor that takes a only. ]]> @@ -624,7 +971,103 @@ The name of the resource to get. Returns the value of the specified non-string resource. The value of the resource localized for the caller's current culture settings. If an appropriate resource set exists but cannot be found, the method returns . - For more information about this API, see Supplemental API remarks for ResourceManager.GetObject. + + method is used to retrieve non-string resources. These include values that belong to primitive data types such as or , bitmaps (such as a object), or custom serialized objects. Typically, the returned object must be cast (in C#) or converted (in Visual Basic) to an object of the appropriate type. + +The property determines whether the comparison of `name` with the names of resources is case-insensitive or case-sensitive (the default). + +> [!NOTE] +> These methods can throw more exceptions than are listed. One reason this might occur is if a method that this method calls throws an exception. For example, a exception might be thrown if an error was made deploying or installing a satellite assembly, or a exception might be thrown if a user-defined type throws a user-defined exception when the type is deserialized. + +## method + +The returned resource is localized for the UI culture of the current thread, which is defined by the property. If the resource is not localized for that culture, the resource manager uses fallback rules to load an appropriate resource. If no usable set of localized resources is found, the falls back on the default culture's resources. If a resource set for the default culture is not found, the method throws a exception or, if the resource set is expected to reside in a satellite assembly, a exception. If the resource manager can load an appropriate resource set but cannot find a resource named `name`, the method returns `null`. + +### Example + +The following example uses the method to deserialize a custom object. The example includes a source code file named UIElements.cs (UIElements.vb if you're using Visual Basic) that defines the following structure named `PersonTable`. This structure is intended to be used by a general table display routine that displays the localized names of table columns. Note that the `PersonTable` structure is marked with the attribute. + +:::code language="csharp" source="~/snippets/csharp/System.Resources/ResourceManager/Overview/example1.cs" id="Snippet6"::: +:::code language="vb" source="~/snippets/visualbasic/System.Resources/ResourceManager/GetObject/example.vb" id="Snippet6"::: + +The following code from a file named CreateResources.cs (or CreateResources.vb for Visual Basic) creates an XML resource file named UIResources.resx that stores a table title and a `PersonTable` object that contains information for an app that is localized for the English language. + +:::code language="csharp" source="~/snippets/csharp/System.Resources/ResourceManager/Overview/example11.cs" id="Snippet7"::: +:::code language="vb" source="~/snippets/visualbasic/System.Resources/ResourceManager/GetObject/example.vb" id="Snippet7"::: + +The following code in a source code file named GetObject.cs (or GetObject.vb) then retrieves the resources and displays them to the console. + +:::code language="csharp" source="~/snippets/csharp/System.Resources/ResourceManager/Overview/example2.cs" id="Snippet8"::: +:::code language="vb" source="~/snippets/visualbasic/System.Resources/ResourceManager/GetObject/example2.vb" id="Snippet8"::: + +You can build the necessary resource file and assemblies and run the app by executing the following batch file. You must use the `/r` option to supply Resgen.exe with a reference to UIElements.dll so that it can access information about the `PersonTable` structure. If you're using C#, replace the `vbc` compiler name with `csc`, and replace the `.vb` extension with `.cs`. + +``` +vbc /t:library UIElements.vb +vbc CreateResources.vb /r:UIElements.dll +CreateResources + +resgen UIResources.resx /r:UIElements.dll +vbc GetObject.vb /r:UIElements.dll /resource:UIResources.resources + +GetObject.exe +``` + +## method + +The returned resource is localized for the culture that is specified by `culture`, or for the culture that is specified by the property if `culture` is `null`. If the resource is not localized for that culture, the resource manager uses fallback rules to load an appropriate resource. If no usable set of localized resources is found, the resource manager falls back on the default culture's resources. If a resource set for the default culture is not found, the method throws a exception or, if the resource set is expected to reside in a satellite assembly, a exception. If the resource manager can load an appropriate resource set but cannot find a resource named `name`, the method returns `null`. + +### Example + +The following example uses the method to deserialize a custom object. The example includes a source code file named NumberInfo.cs (NumberInfo.vb if you're using Visual Basic) that defines the following structure named `Numbers`. This structure is intended to be used by a simple educational app that teaches non-English speaking students to count to ten in English. Note that the `Numbers` class is marked with the attribute. + +:::code language="csharp" source="~/snippets/csharp/System.Resources/ResourceManager/GetObject/numberinfo.cs" id="Snippet1"::: +:::code language="vb" source="~/snippets/visualbasic/System.Resources/ResourceManager/GetObject/numberinfo.vb" id="Snippet1"::: + +The following source code from a file named CreateResources.cs (CreateResources.vb for Visual Basic) creates XML resource files for the default English language, as well as for the French, Portuguese, and Russian languages. + +:::code language="csharp" source="~/snippets/csharp/System.Resources/ResourceManager/GetObject/createresources.cs" id="Snippet2"::: +:::code language="vb" source="~/snippets/visualbasic/System.Resources/ResourceManager/GetObject/createresources.vb" id="Snippet2"::: + +The resources are consumed by the following app, which sets the current UI culture to French (France), Portuguese (Brazil), or Russian (Russia). It calls the method to get a `Numbers` object that contains localized numbers and the method to get a `Numbers` object that contains English language numbers. It then displays odd numbers using the current UI culture and the English language. The source code file is named ShowNumbers.cs (ShowNumbers.vb). + +:::code language="csharp" source="~/snippets/csharp/System.Resources/ResourceManager/GetObject/shownumbers.cs" id="Snippet3"::: +:::code language="vb" source="~/snippets/visualbasic/System.Resources/ResourceManager/GetObject/shownumbers.vb" id="Snippet3"::: + +You can use the following batch file to build and execute the Visual Basic version of the example. If you're using C#, replace `vbc` with `csc`, and replace the `.vb` extension with `.cs`. + +``` +vbc /t:library NumberInfo.vb + +vbc CreateResources.vb /r:NumberInfo.dll +CreateResources + +resgen NumberResources.resx /r:NumberInfo.dll + +resgen NumberResources.fr.resx /r:Numberinfo.dll +Md fr +al /embed:NumberResources.fr.resources /culture:fr /t:lib /out:fr\ShowNumbers.resources.dll + +resgen NumberResources.pt.resx /r:Numberinfo.dll +Md pt +al /embed:NumberResources.pt.resources /culture:pt /t:lib /out:pt\ShowNumbers.resources.dll + +resgen NumberResources.ru.resx /r:Numberinfo.dll +Md ru +al /embed:NumberResources.ru.resources /culture:ru /t:lib /out:ru\ShowNumbers.resources.dll + +vbc ShowNumbers.vb /r:NumberInfo.dll /resource:NumberResources.resources +ShowNumbers.exe +``` + +## Performance considerations + +If you call the method multiple times with the same `name` parameter, do not depend on the method returning a reference to the same object with each call. This is because the method can return a reference to an existing resource object in a cache, or it can reload the resource and return a reference to a new resource object. + + ]]> + The parameter is . No usable set of localized resources has been found, and there are no default culture resources. For information about how to handle this exception, see the "Handling MissingManifestResourceException and MissingSatelliteAssemblyException Exceptions" section in the class topic. The default culture's resources reside in a satellite assembly that could not be found. For information about how to handle this exception, see the "Handling MissingManifestResourceException and MissingSatelliteAssemblyException Exceptions" section in the class topic. @@ -690,7 +1133,103 @@ If this value is , the object is obtained by using the property. Gets the value of the specified non-string resource localized for the specified culture. The value of the resource, localized for the specified culture. If an appropriate resource set exists but cannot be found, the method returns . - For more information about this API, see Supplemental API remarks for ResourceManager.GetObject. + + method is used to retrieve non-string resources. These include values that belong to primitive data types such as or , bitmaps (such as a object), or custom serialized objects. Typically, the returned object must be cast (in C#) or converted (in Visual Basic) to an object of the appropriate type. + +The property determines whether the comparison of `name` with the names of resources is case-insensitive or case-sensitive (the default). + +> [!NOTE] +> These methods can throw more exceptions than are listed. One reason this might occur is if a method that this method calls throws an exception. For example, a exception might be thrown if an error was made deploying or installing a satellite assembly, or a exception might be thrown if a user-defined type throws a user-defined exception when the type is deserialized. + +## method + +The returned resource is localized for the UI culture of the current thread, which is defined by the property. If the resource is not localized for that culture, the resource manager uses fallback rules to load an appropriate resource. If no usable set of localized resources is found, the falls back on the default culture's resources. If a resource set for the default culture is not found, the method throws a exception or, if the resource set is expected to reside in a satellite assembly, a exception. If the resource manager can load an appropriate resource set but cannot find a resource named `name`, the method returns `null`. + +### Example + +The following example uses the method to deserialize a custom object. The example includes a source code file named UIElements.cs (UIElements.vb if you're using Visual Basic) that defines the following structure named `PersonTable`. This structure is intended to be used by a general table display routine that displays the localized names of table columns. Note that the `PersonTable` structure is marked with the attribute. + +:::code language="csharp" source="~/snippets/csharp/System.Resources/ResourceManager/Overview/example1.cs" id="Snippet6"::: +:::code language="vb" source="~/snippets/visualbasic/System.Resources/ResourceManager/GetObject/example.vb" id="Snippet6"::: + +The following code from a file named CreateResources.cs (or CreateResources.vb for Visual Basic) creates an XML resource file named UIResources.resx that stores a table title and a `PersonTable` object that contains information for an app that is localized for the English language. + +:::code language="csharp" source="~/snippets/csharp/System.Resources/ResourceManager/Overview/example11.cs" id="Snippet7"::: +:::code language="vb" source="~/snippets/visualbasic/System.Resources/ResourceManager/GetObject/example.vb" id="Snippet7"::: + +The following code in a source code file named GetObject.cs (or GetObject.vb) then retrieves the resources and displays them to the console. + +:::code language="csharp" source="~/snippets/csharp/System.Resources/ResourceManager/Overview/example2.cs" id="Snippet8"::: +:::code language="vb" source="~/snippets/visualbasic/System.Resources/ResourceManager/GetObject/example2.vb" id="Snippet8"::: + +You can build the necessary resource file and assemblies and run the app by executing the following batch file. You must use the `/r` option to supply Resgen.exe with a reference to UIElements.dll so that it can access information about the `PersonTable` structure. If you're using C#, replace the `vbc` compiler name with `csc`, and replace the `.vb` extension with `.cs`. + +``` +vbc /t:library UIElements.vb +vbc CreateResources.vb /r:UIElements.dll +CreateResources + +resgen UIResources.resx /r:UIElements.dll +vbc GetObject.vb /r:UIElements.dll /resource:UIResources.resources + +GetObject.exe +``` + +## method + +The returned resource is localized for the culture that is specified by `culture`, or for the culture that is specified by the property if `culture` is `null`. If the resource is not localized for that culture, the resource manager uses fallback rules to load an appropriate resource. If no usable set of localized resources is found, the resource manager falls back on the default culture's resources. If a resource set for the default culture is not found, the method throws a exception or, if the resource set is expected to reside in a satellite assembly, a exception. If the resource manager can load an appropriate resource set but cannot find a resource named `name`, the method returns `null`. + +### Example + +The following example uses the method to deserialize a custom object. The example includes a source code file named NumberInfo.cs (NumberInfo.vb if you're using Visual Basic) that defines the following structure named `Numbers`. This structure is intended to be used by a simple educational app that teaches non-English speaking students to count to ten in English. Note that the `Numbers` class is marked with the attribute. + +:::code language="csharp" source="~/snippets/csharp/System.Resources/ResourceManager/GetObject/numberinfo.cs" id="Snippet1"::: +:::code language="vb" source="~/snippets/visualbasic/System.Resources/ResourceManager/GetObject/numberinfo.vb" id="Snippet1"::: + +The following source code from a file named CreateResources.cs (CreateResources.vb for Visual Basic) creates XML resource files for the default English language, as well as for the French, Portuguese, and Russian languages. + +:::code language="csharp" source="~/snippets/csharp/System.Resources/ResourceManager/GetObject/createresources.cs" id="Snippet2"::: +:::code language="vb" source="~/snippets/visualbasic/System.Resources/ResourceManager/GetObject/createresources.vb" id="Snippet2"::: + +The resources are consumed by the following app, which sets the current UI culture to French (France), Portuguese (Brazil), or Russian (Russia). It calls the method to get a `Numbers` object that contains localized numbers and the method to get a `Numbers` object that contains English language numbers. It then displays odd numbers using the current UI culture and the English language. The source code file is named ShowNumbers.cs (ShowNumbers.vb). + +:::code language="csharp" source="~/snippets/csharp/System.Resources/ResourceManager/GetObject/shownumbers.cs" id="Snippet3"::: +:::code language="vb" source="~/snippets/visualbasic/System.Resources/ResourceManager/GetObject/shownumbers.vb" id="Snippet3"::: + +You can use the following batch file to build and execute the Visual Basic version of the example. If you're using C#, replace `vbc` with `csc`, and replace the `.vb` extension with `.cs`. + +``` +vbc /t:library NumberInfo.vb + +vbc CreateResources.vb /r:NumberInfo.dll +CreateResources + +resgen NumberResources.resx /r:NumberInfo.dll + +resgen NumberResources.fr.resx /r:Numberinfo.dll +Md fr +al /embed:NumberResources.fr.resources /culture:fr /t:lib /out:fr\ShowNumbers.resources.dll + +resgen NumberResources.pt.resx /r:Numberinfo.dll +Md pt +al /embed:NumberResources.pt.resources /culture:pt /t:lib /out:pt\ShowNumbers.resources.dll + +resgen NumberResources.ru.resx /r:Numberinfo.dll +Md ru +al /embed:NumberResources.ru.resources /culture:ru /t:lib /out:ru\ShowNumbers.resources.dll + +vbc ShowNumbers.vb /r:NumberInfo.dll /resource:NumberResources.resources +ShowNumbers.exe +``` + +## Performance considerations + +If you call the method multiple times with the same `name` parameter, do not depend on the method returning a reference to the same object with each call. This is because the method can return a reference to an existing resource object in a cache, or it can reload the resource and return a reference to a new resource object. + + ]]> + The parameter is . No usable set of resources have been found, and there are no default culture resources. For information about how to handle this exception, see the "Handling MissingManifestResourceException and MissingSatelliteAssemblyException Exceptions" section in the class topic. The default culture's resources reside in a satellite assembly that could not be found. For information about how to handle this exception, see the "Handling MissingManifestResourceException and MissingSatelliteAssemblyException Exceptions" section in the class topic. @@ -1205,7 +1744,106 @@ csc GetStream.cs /resource:AppResources.resources The name of the resource to retrieve. Returns the value of the specified string resource. The value of the resource localized for the caller's current UI culture, or if cannot be found in a resource set. - For more information about this API, see Supplemental API remarks for ResourceManager.GetString. + + property determines whether the comparison of `name` with the names of resources is case-insensitive (the default) or case-sensitive. + +> [!NOTE] +> The methods can throw more exceptions than are listed. One reason this might occur is if a method that this method calls throws an exception. For example, a exception might be thrown if an error was made deploying or installing a satellite assembly, or a exception might be thrown if a user-defined type throws a user-defined exception when the type is deserialized. + +## method + +### Desktop apps + +In desktop apps, the resource that is returned is localized for the UI culture of the current thread, as defined by the property. If the resource has not been localized for that culture, the resource manager probes for a resource by following the steps outlined in the "Resource Fallback Process" section of the [Packaging and Deploying Resources](/dotnet/framework/resources/packaging-and-deploying-resources-in-desktop-apps) article. If no usable set of localized resources is found, the resource manager falls back on the default culture's resources. If the resource manager cannot load the default culture's resource set, the method throws a exception or, if the resource set is expected to reside in a satellite assembly, a exception. If the resource manager can load an appropriate resource set but cannot find a resource named `name`, the method returns `null`. + +### Windows 8.x apps + +> [!IMPORTANT] +> Although the class is supported in Windows 8.x apps, we do not recommend its use. Use this class only when you develop Portable Class Library projects that can be used with Windows 8.x apps. To retrieve resources from Windows 8.x apps, use the [Windows.ApplicationModel.Resources.ResourceLoader](/uwp/api/windows.applicationmodel.resources.resourceloader) class instead. + +In Windows 8.x apps, the method returns the value of the `name` string resource, localized for the caller's current UI culture settings. The list of cultures is derived from the operating system's preferred UI language list. If the resource manager cannot match `name`, the method returns `null`. + +### Example + +The following example uses the method to retrieve culture-specific resources. It consists of resources compiled from .txt files for the English (en), French (France) (fr-FR), and Russian (Russia) (ru-RU) cultures. The example changes the current culture and current UI culture to English (United States), French (France), Russian (Russia), and Swedish (Sweden). It then calls the method to retrieve the localized string, which it displays along with the current day and month. Notice that the output displays the appropriate localized string except when the current UI culture is Swedish (Sweden). Because Swedish language resources are unavailable, the app instead uses the resources of the default culture, which is English. The example requires the text-based resource files listed in following table. Each has a single string resource named `DateStart`. + +| Culture | File name | Resource name | Resource value | +|---------|-----------------------|---------------|-----------------------| +| en-US | DateStrings.txt | `DateStart` | Today is | +| fr-FR | DateStrings.fr-FR.txt | `DateStart` | Aujourd'hui, c'est le | +| ru-RU | DateStrings.ru-RU.txt | `DateStart` | Сегодня | + +You can use the following batch file to compile the C# example. For Visual Basic, change `csc` to `vbc`, and change the extension of the source code file from `.cs` to `.vb`. + +``` +resgen DateStrings.txt +csc showdate.cs /resource:DateStrings.resources + +md fr-FR +resgen DateStrings.fr-FR.txt +al /out:fr-FR\Showdate.resources.dll /culture:fr-FR /embed:DateStrings.fr-FR.resources + +md ru-RU +resgen DateStrings.ru-RU.txt +al /out:ru-RU\Showdate.resources.dll /culture:ru-RU /embed:DateStrings.ru-RU.resources +``` + +Here's the source code for the example (ShowDate.vb for the Visual Basic version or ShowDate.cs for the C# version). + +:::code language="csharp" source="~/snippets/csharp/System.Resources/MissingManifestResourceException/Overview/showdate1.cs" id="Snippet2"::: +:::code language="vb" source="~/snippets/visualbasic/System.Resources/ResourceManager/GetString/showdate.vb" id="Snippet2"::: + +## method + +### Desktop apps + +In desktop apps, if `culture` is `null`, the method uses the current UI culture obtained from the property. + +The resource that is returned is localized for the culture specified by the `culture` parameter. If the resource has not been localized for `culture`, the resource manager probes for a resource by following the steps outlined in the "Resource Fallback Process" section of the [Packaging and Deploying Resources](/dotnet/framework/resources/packaging-and-deploying-resources-in-desktop-apps) topic. If no usable set of resources is found, the resource manager falls back on the default culture's resources. If the resource manager cannot load the default culture's resource set, the method throws a exception or, if the resource set is expected to reside in a satellite assembly, a exception. If the resource manager can load an appropriate resource set but cannot find a resource named `name`, the method returns `null`. + +### Windows 8.x apps + +> [!IMPORTANT] +> Although the class is supported in Windows 8.x apps, we do not recommend its use. Use this class only when you develop Portable Class Library projects that can be used with Windows 8.x apps. To retrieve resources from Windows 8.x apps, use the [Windows.ApplicationModel.Resources.ResourceLoader](/uwp/api/windows.applicationmodel.resources.resourceloader) class instead. + +In Windows 8.x apps, the method returns the value of the `name` string resource, localized for the culture specified by the `culture` parameter. If the resource is not localized for the `culture` culture, the lookup uses the entire Windows 8 language fallback list, and stops after looking in the default culture. If the resource manager cannot match `name`, the method returns `null`. + +### Example + +The following example uses the method to retrieve culture-specific resources. The example's default culture is English (en), and it includes satellite assemblies for the French (France) (fr-FR) and Russian (Russia) (ru-RU) cultures. The example changes the current culture and current UI culture to Russian (Russia) before calling . It then calls the method and the method and passes objects that represent the French (France) and Swedish (Sweden) cultures to each method. In the output, the month and day of the month as well as the string that precedes them appear in French, because the method is able to retrieve the French language resource. However, when the Swedish (Sweden) culture is used, the month and day of the month appear in Swedish, although the string that precedes them is in English. This is because the resource manager cannot find localized Swedish language resources, so it returns a resource for the default English culture instead. + +The example requires the text-based resource files listed in following table. Each has a single string resource named `DateStart`. + +| Culture | File name | Resource name | Resource value | +|---------|-----------------------|---------------|-----------------------| +| en-US | DateStrings.txt | `DateStart` | Today is | +| fr-FR | DateStrings.fr-FR.txt | `DateStart` | Aujourd'hui, c'est le | +| ru-RU | DateStrings.ru-RU.txt | `DateStart` | Сегодня | + +You can use the following batch file to compile the Visual Basic example. To compile in C#, change `vbc` to `csc`, and change the extension of the source code file from `.vb` to `.cs`. + +``` +resgen DateStrings.txt +vbc showdate.vb /resource:DateStrings.resources + +md fr-FR +resgen DateStrings.fr-FR.txt +al /out:fr-FR\Showdate.resources.dll /culture:fr-FR /embed:DateStrings.fr-FR.resources + +md ru-RU +resgen DateStrings.ru-RU.txt +al /out:ru-RU\Showdate.resources.dll /culture:ru-RU /embed:DateStrings.ru-RU.resources +``` + +Here's the source code for the example (ShowDate.vb for the Visual Basic version or ShowDate.cs for the C# version). + +:::code language="csharp" source="~/snippets/csharp/System.Resources/MissingManifestResourceException/Overview/showdate2.cs" id="Snippet3"::: +:::code language="vb" source="~/snippets/visualbasic/System.Resources/ResourceManager/GetString/showdate2.vb" id="Snippet3"::: + + ]]> + The parameter is . The value of the specified resource is not a string. No usable set of resources has been found, and there are no resources for the default culture. For information about how to handle this exception, see the "Handling MissingManifestResourceException and MissingSatelliteAssemblyException Exceptions" section in the class topic. @@ -1273,7 +1911,106 @@ csc GetStream.cs /resource:AppResources.resources An object that represents the culture for which the resource is localized. Returns the value of the string resource localized for the specified culture. The value of the resource localized for the specified culture, or if cannot be found in a resource set. - For more information about this API, see Supplemental API remarks for ResourceManager.GetString. + + property determines whether the comparison of `name` with the names of resources is case-insensitive (the default) or case-sensitive. + +> [!NOTE] +> The methods can throw more exceptions than are listed. One reason this might occur is if a method that this method calls throws an exception. For example, a exception might be thrown if an error was made deploying or installing a satellite assembly, or a exception might be thrown if a user-defined type throws a user-defined exception when the type is deserialized. + +## method + +### Desktop apps + +In desktop apps, the resource that is returned is localized for the UI culture of the current thread, as defined by the property. If the resource has not been localized for that culture, the resource manager probes for a resource by following the steps outlined in the "Resource Fallback Process" section of the [Packaging and Deploying Resources](/dotnet/framework/resources/packaging-and-deploying-resources-in-desktop-apps) article. If no usable set of localized resources is found, the resource manager falls back on the default culture's resources. If the resource manager cannot load the default culture's resource set, the method throws a exception or, if the resource set is expected to reside in a satellite assembly, a exception. If the resource manager can load an appropriate resource set but cannot find a resource named `name`, the method returns `null`. + +### Windows 8.x apps + +> [!IMPORTANT] +> Although the class is supported in Windows 8.x apps, we do not recommend its use. Use this class only when you develop Portable Class Library projects that can be used with Windows 8.x apps. To retrieve resources from Windows 8.x apps, use the [Windows.ApplicationModel.Resources.ResourceLoader](/uwp/api/windows.applicationmodel.resources.resourceloader) class instead. + +In Windows 8.x apps, the method returns the value of the `name` string resource, localized for the caller's current UI culture settings. The list of cultures is derived from the operating system's preferred UI language list. If the resource manager cannot match `name`, the method returns `null`. + +### Example + +The following example uses the method to retrieve culture-specific resources. It consists of resources compiled from .txt files for the English (en), French (France) (fr-FR), and Russian (Russia) (ru-RU) cultures. The example changes the current culture and current UI culture to English (United States), French (France), Russian (Russia), and Swedish (Sweden). It then calls the method to retrieve the localized string, which it displays along with the current day and month. Notice that the output displays the appropriate localized string except when the current UI culture is Swedish (Sweden). Because Swedish language resources are unavailable, the app instead uses the resources of the default culture, which is English. The example requires the text-based resource files listed in following table. Each has a single string resource named `DateStart`. + +| Culture | File name | Resource name | Resource value | +|---------|-----------------------|---------------|-----------------------| +| en-US | DateStrings.txt | `DateStart` | Today is | +| fr-FR | DateStrings.fr-FR.txt | `DateStart` | Aujourd'hui, c'est le | +| ru-RU | DateStrings.ru-RU.txt | `DateStart` | Сегодня | + +You can use the following batch file to compile the C# example. For Visual Basic, change `csc` to `vbc`, and change the extension of the source code file from `.cs` to `.vb`. + +``` +resgen DateStrings.txt +csc showdate.cs /resource:DateStrings.resources + +md fr-FR +resgen DateStrings.fr-FR.txt +al /out:fr-FR\Showdate.resources.dll /culture:fr-FR /embed:DateStrings.fr-FR.resources + +md ru-RU +resgen DateStrings.ru-RU.txt +al /out:ru-RU\Showdate.resources.dll /culture:ru-RU /embed:DateStrings.ru-RU.resources +``` + +Here's the source code for the example (ShowDate.vb for the Visual Basic version or ShowDate.cs for the C# version). + +:::code language="csharp" source="~/snippets/csharp/System.Resources/MissingManifestResourceException/Overview/showdate1.cs" id="Snippet2"::: +:::code language="vb" source="~/snippets/visualbasic/System.Resources/ResourceManager/GetString/showdate.vb" id="Snippet2"::: + +## method + +### Desktop apps + +In desktop apps, if `culture` is `null`, the method uses the current UI culture obtained from the property. + +The resource that is returned is localized for the culture specified by the `culture` parameter. If the resource has not been localized for `culture`, the resource manager probes for a resource by following the steps outlined in the "Resource Fallback Process" section of the [Packaging and Deploying Resources](/dotnet/framework/resources/packaging-and-deploying-resources-in-desktop-apps) topic. If no usable set of resources is found, the resource manager falls back on the default culture's resources. If the resource manager cannot load the default culture's resource set, the method throws a exception or, if the resource set is expected to reside in a satellite assembly, a exception. If the resource manager can load an appropriate resource set but cannot find a resource named `name`, the method returns `null`. + +### Windows 8.x apps + +> [!IMPORTANT] +> Although the class is supported in Windows 8.x apps, we do not recommend its use. Use this class only when you develop Portable Class Library projects that can be used with Windows 8.x apps. To retrieve resources from Windows 8.x apps, use the [Windows.ApplicationModel.Resources.ResourceLoader](/uwp/api/windows.applicationmodel.resources.resourceloader) class instead. + +In Windows 8.x apps, the method returns the value of the `name` string resource, localized for the culture specified by the `culture` parameter. If the resource is not localized for the `culture` culture, the lookup uses the entire Windows 8 language fallback list, and stops after looking in the default culture. If the resource manager cannot match `name`, the method returns `null`. + +### Example + +The following example uses the method to retrieve culture-specific resources. The example's default culture is English (en), and it includes satellite assemblies for the French (France) (fr-FR) and Russian (Russia) (ru-RU) cultures. The example changes the current culture and current UI culture to Russian (Russia) before calling . It then calls the method and the method and passes objects that represent the French (France) and Swedish (Sweden) cultures to each method. In the output, the month and day of the month as well as the string that precedes them appear in French, because the method is able to retrieve the French language resource. However, when the Swedish (Sweden) culture is used, the month and day of the month appear in Swedish, although the string that precedes them is in English. This is because the resource manager cannot find localized Swedish language resources, so it returns a resource for the default English culture instead. + +The example requires the text-based resource files listed in following table. Each has a single string resource named `DateStart`. + +| Culture | File name | Resource name | Resource value | +|---------|-----------------------|---------------|-----------------------| +| en-US | DateStrings.txt | `DateStart` | Today is | +| fr-FR | DateStrings.fr-FR.txt | `DateStart` | Aujourd'hui, c'est le | +| ru-RU | DateStrings.ru-RU.txt | `DateStart` | Сегодня | + +You can use the following batch file to compile the Visual Basic example. To compile in C#, change `vbc` to `csc`, and change the extension of the source code file from `.vb` to `.cs`. + +``` +resgen DateStrings.txt +vbc showdate.vb /resource:DateStrings.resources + +md fr-FR +resgen DateStrings.fr-FR.txt +al /out:fr-FR\Showdate.resources.dll /culture:fr-FR /embed:DateStrings.fr-FR.resources + +md ru-RU +resgen DateStrings.ru-RU.txt +al /out:ru-RU\Showdate.resources.dll /culture:ru-RU /embed:DateStrings.ru-RU.resources +``` + +Here's the source code for the example (ShowDate.vb for the Visual Basic version or ShowDate.cs for the C# version). + +:::code language="csharp" source="~/snippets/csharp/System.Resources/MissingManifestResourceException/Overview/showdate2.cs" id="Snippet3"::: +:::code language="vb" source="~/snippets/visualbasic/System.Resources/ResourceManager/GetString/showdate2.vb" id="Snippet3"::: + + ]]> + The parameter is . The value of the specified resource is not a string. No usable set of resources has been found, and there are no resources for a default culture. For information about how to handle this exception, see the "Handling MissingManifestResourceException and MissingSatelliteAssemblyException Exceptions" section in the class topic. diff --git a/xml/System.Resources/ResourceReader.xml b/xml/System.Resources/ResourceReader.xml index e8f4891b46f..400080978cc 100644 --- a/xml/System.Resources/ResourceReader.xml +++ b/xml/System.Resources/ResourceReader.xml @@ -89,7 +89,111 @@ Enumerates the resources in a binary resources (.resources) file by reading sequential resource name/value pairs. - For more information about this API, see Supplemental API remarks for ResourceReader. + + class provides a standard implementation of the interface. A instance represents either a standalone .resources file or a .resources file that is embedded in an assembly. It is used to enumerate the resources in a .resources file and retrieve its name/value pairs. It differs from the class, which is used to retrieve specified named resources from a .resources file that is embedded in an assembly. The class is used to retrieve resources whose names are known in advance, whereas the class is useful for retrieving resources whose number or precise names are not known at compile time. For example, an application may use a resources file to store configuration information that is organized into sections and items in a section, where the number of sections or items in a section is not known in advance. Resources can then be named generically (such as `Section1`, `Section1Item1`, `Section1Item2`, and so on) and retrieved by using a object. + +> [!IMPORTANT] +> This type implements the interface. When you have finished using the type, you should dispose of it either directly or indirectly. To dispose of the type directly, call its method in a `try`/`catch` block. To dispose of it indirectly, use a language construct such as `using` (in C#) or `Using` (in Visual Basic). For more information, see the "Using an Object that Implements IDisposable" section in the interface documentation. + +## Instantiate a ResourceReader object + +A .resources file is a binary file that has been compiled from either a text file or an XML .resx file by [Resgen.exe (Resource File Generator)](/dotnet/framework/tools/resgen-exe-resource-file-generator). A object can represent either a standalone .resources file or a .resources file that has been embedded in an assembly. + +To instantiate a object that reads from a standalone .resources file, use the class constructor with either an input stream or a string that contains the .resources file name. The following example illustrates both approaches. The first instantiates a object that represents a .resources file named `Resources1.resources` by using its file name. The second instantiates a object that represents a .resources file named `Resources2.resources` by using a stream created from the file. + +:::code language="csharp" source="~/snippets/csharp/System.Resources/ResourceReader/Overview/ctor1.cs" id="Snippet2"::: +:::code language="vb" source="~/snippets/visualbasic/System.Resources/ResourceReader/Overview/ctor1.vb" id="Snippet2"::: + +To create a object that represents an embedded .resources file, instantiate an object from the assembly in which the .resources file is embedded. Its method returns a object that can be passed to the constructor. The following example instantiates a object that represents an embedded .resources file. + +:::code language="csharp" source="~/snippets/csharp/System.Resources/ResourceReader/Overview/ctor1.cs" id="Snippet3"::: +:::code language="vb" source="~/snippets/visualbasic/System.Resources/ResourceReader/Overview/ctor1.vb" id="Snippet3"::: + +## Enumerate a ResourceReader object's resources + +To enumerate the resources in a .resources file, you call the method, which returns an object. You call the `IDictionaryEnumerator.MoveNext` method to move from one resource to the next. The method returns `false` when all the resources in the .resources file have been enumerated. + +> [!NOTE] +> Although the class implements the interface and the method, the method does not provide the implementation. Instead, the method returns an interface object that provides access to each resource's name/value pair. + +You can retrieve the individual resources in the collection in two ways: + +- You can iterate each resource in the collection and use properties to retrieve the resource name and value. We recommend this technique when all the resources are of the same type, or you know the data type of each resource. + +- You can retrieve the name of each resource when you iterate the collection and call the method to retrieve the resource's data. We recommend this approach when you do not know the data type of each resource or if the previous approach throws exceptions. + +### Retrieve resources by using IDictionaryEnumerator properties + +The first method of enumerating the resources in a .resources file involves directly retrieving each resource's name/value pair. After you call the `IDictionaryEnumerator.MoveNext` method to move to each resource in the collection, you can retrieve the resource name from the property and the resource data from the property. + +The following example shows how to retrieve the name and value of each resource in a .resources file by using the and properties. To run the example, create the following text file named ApplicationResources.txt to define string resources. + +``` +Title="Contact Information" +Label1="First Name:" +Label2="Middle Name:" +Label3="Last Name:" +Label4="SSN:" +Label5="Street Address:" +Label6="City:" +Label7="State:" +Label8="Zip Code:" +Label9="Home Phone:" +Label10="Business Phone:" +Label11="Mobile Phone:" +Label12="Other Phone:" +Label13="Fax:" +Label14="Email Address:" +Label15="Alternate Email Address:" +``` + +You can then convert the text resource file to a binary file named ApplicationResources.resources by using the following command: + +`resgen ApplicationResources.txt` + +The following example then uses the class to enumerate each resource in the standalone binary .resources file and to display its key name and corresponding value. + +:::code language="csharp" source="~/snippets/csharp/System.Resources/ResourceReader/Overview/class1.cs" id="Snippet1"::: +:::code language="vb" source="~/snippets/visualbasic/System.Resources/ResourceReader/Overview/class1.vb" id="Snippet1"::: + +The attempt to retrieve resource data from the property can throw the following exceptions: + +- A if the data is not in the expected format. +- A if the assembly that contains the type to which the data belongs can't be found. +- A if the type to which the data belongs can't be found. + +Typically, these exceptions are thrown if the .resources file has been modified manually, if the assembly in which a type is defined has either not been included with an application or has been inadvertently deleted, or if the assembly is an older version that predates a type. If one of these exceptions is thrown, you can retrieve resources by enumerating each resource and calling the method, as the following section shows. This approach provides you with some information about the data type that the property attempted to return. + +### Retrieve resources by name with GetResourceData + +The second approach to enumerating resources in a .resources file also involves navigating through the resources in the file by calling the `IDictionaryEnumerator.MoveNext` method. For each resource, you retrieve the resource's name from the property, which is then passed to the method to retrieve the resource's data. This is returned as a byte array in the `resourceData` argument. + +This approach is more awkward than retrieving the resource name and value from the and properties, because it returns the actual bytes that form the resource value. However, if the attempt to retrieve the resource throws an exception, the method can help identify the source of the exception by supplying information about the resource's data type. For more information about the string that indicates the resource's data type, see . + +The following example illustrates how to use this approach to retrieve resources and to handle any exceptions that are thrown. It programmatically creates a binary .resources file that contains four strings, one Boolean, one integer, and one bitmap. To run the example, do the following: + +1. Compile and execute the following source code, which creates a .resources file named ContactResources.resources. + + :::code language="csharp" source="~/snippets/csharp/System.Resources/ResourceReader/Overview/createresourceex1.cs" id="Snippet5"::: + + The source code file is named CreateResources.cs. You can compile it in C# by using the following command: + + ``` + csc CreateResources.cs /r:library.dll + ``` + +2. Compile and run the following code to enumerate the resources in the ContactResources.resources file. + + :::code language="csharp" source="~/snippets/csharp/System.Resources/ResourceReader/Overview/readresourceex1.cs" id="Snippet6"::: + + After modifying the source code (for example, by deliberately throwing a at the end of the `try` block), you can run the example to see how calls to enable you to retrieve or recreate some resource information. + + ]]> + diff --git a/xml/System.Resources/SatelliteContractVersionAttribute.xml b/xml/System.Resources/SatelliteContractVersionAttribute.xml index 9b16b2e287d..a8dd8a5e698 100644 --- a/xml/System.Resources/SatelliteContractVersionAttribute.xml +++ b/xml/System.Resources/SatelliteContractVersionAttribute.xml @@ -70,7 +70,23 @@ Instructs a object to ask for a particular version of a satellite assembly. - For more information about this API, see Supplemental API remarks for SatelliteContractVersionAttribute. + + attribute establishes a contract between a main assembly and all its satellites. You apply this attribute to your main assembly, and pass it the version number of the satellite assemblies that will work with this version of the main assembly. When the resource manager ( object) looks up resources, it explicitly loads the satellite version specified by this attribute on the main assembly. + +When you update the main assembly, you increment its assembly version number. However, you might not want to ship new copies of your satellite assemblies if the existing ones are compatible with your app. In this case, increment the main assembly's version number but leave the satellite contract version number the same. The resource manager will use your existing satellite assemblies. + +If you want to revise a satellite assembly but not the main assembly, increment the version number on your satellite. In this case, ship a publisher policy assembly along with your satellite assembly stating that your new satellite assembly has backward compatibility with your old satellite assembly. The resource manager will still use the old contract number written into your main assembly based on the attribute; however, the loader will bind to the satellite assembly version that is specified by the policy assembly. + +A vendor of a shared component uses a publisher policy assembly to make a compatibility statement about a particular version of a released assembly. A publisher policy assembly is a strongly named assembly that has a name in the format `policy...`, and is registered in the [Global Assembly Cache (GAC)](/dotnet/framework/app-domains/gac). The publisher policy is generated from an XML configuration file (see the [`` Element](/dotnet/framework/configure-apps/file-schema/runtime/bindingredirect-element)) by using the [Al.exe (Assembly Linker)](/dotnet/framework/tools/al-exe-assembly-linker) tool. The Assembly Linker is used with the `/link` option to link the XML configuration file to a manifest assembly, which is then stored in the global assembly cache. The publisher policy assemblies can be used when a vendor ships a maintenance release (service pack) that contains bug fixes. + +## Windows 8.x Store apps + +This attribute is ignored in Windows 8.x Store apps, because package resource index (PRI) files do not have versioning semantics. In addition, the Windows 8.x Store packaging model requires all resources to ship in the same package, with no possibility of redeploying satellite assemblies or PRI files. + + ]]> +