1

I'm getting a TypeInitializationException using NodaTime, but only in Release and only on devices.

Here's the stack trace:

System.TypeInitializationException: The type initializer for 'Patterns' threw an exception. ---> System.TypeInitializationException: The type initializer for 'NodaTime.Text.ZonedDateTimePattern' threw an exception. ---> System.TypeInitializationException: The type initializer for 'NodaTime.DateTimeZone' threw an exception. ---> System.TypeInitializationException: The type initializer for 'NodaTime.Text.OffsetPattern' threw an exception. ---> System.Resources.MissingManifestResourceException: Exception of type 'System.Resources.MissingManifestResourceException' was thrown.
   at System.Resources.ResourceManager.GetString(String name, CultureInfo culture)
   at NodaTime.Globalization.NodaFormatInfo.get_OffsetPatternLong()
   at NodaTime.Text.OffsetPatternParser.ParsePartialPattern(String patternText, NodaFormatInfo formatInfo)
   at NodaTime.Text.OffsetPatternParser.CreateGeneralPattern(NodaFormatInfo formatInfo)
   at NodaTime.Text.OffsetPatternParser.ParsePartialPattern(String patternText, NodaFormatInfo formatInfo)
   at NodaTime.Text.OffsetPatternParser.ParsePattern(String patternText, NodaFormatInfo formatInfo)
   at NodaTime.Text.FixedFormatInfoPatternParser`1.<>c__DisplayClass0.<.ctor>b__2(String patternText)
   at NodaTime.Utility.Cache`2.GetOrAdd(TKey key)
   at NodaTime.Text.OffsetPattern.Create(String patternText, NodaFormatInfo formatInfo)
   at NodaTime.Text.OffsetPattern..cctor()
   --- End of inner exception stack trace ---
   at NodaTime.TimeZones.FixedDateTimeZone.MakeId(Offset offset)
   at NodaTime.DateTimeZone.BuildFixedZoneCache()
   at NodaTime.DateTimeZone..cctor()
   --- End of inner exception stack trace ---
   at NodaTime.LocalDateTime.InUtc()
   at NodaTime.Text.ZonedDateTimePattern..cctor()
   --- End of inner exception stack trace ---
   at NodaTime.Text.ZonedDateTimePattern.CreateWithInvariantCulture(String patternText, IDateTimeZoneProvider zoneProvider)
   at NodaTime.Text.ZonedDateTimePattern.Patterns..cctor()
   --- End of inner exception stack trace ---
   at NodaTime.ZonedDateTime.ToString(String patternText, IFormatProvider formatProvider)
   at System.Text.StringBuilder.AppendFormat(IFormatProvider provider, String format, Object[] args)
   at System.Text.StringBuilder.AppendFormat(String format, Object[] args)
   at Models.EventSummary.get_DisplayDate()
Jeff
  • 5,746
  • 4
  • 33
  • 40
  • Hmm. Interesting. What is your culture? I'd expect it to just fall back to whatever culture I've specified as the one for the assembly... it's not like there are any other cultures with that resource. Hmm. – Jon Skeet Oct 11 '14 at 17:50
  • When you say it's "only in release" - presumably you're using the same Noda Time assembly in both cases, installed bu NuGet? – Jon Skeet Oct 11 '14 at 17:50
  • Yes, everything is set up via NuGet. – Jeff Oct 11 '14 at 18:12
  • Okay, so the NodaTime.dll should be the same on both release and debug. Sounds like this might well be a duplicate of http://stackoverflow.com/questions/26140155 – Jon Skeet Oct 11 '14 at 18:15
  • And also https://github.com/Reactive-Extensions/Rx.NET/issues/13 - looks like it's a framework issue rather than Noda Time, which will make it hard to fix :( – Jon Skeet Oct 11 '14 at 18:16
  • 1
    Based on other comments on Twitter, it *sounds* like resx isn't supported on WP8.1, whereas resw is. I need to investigate this a bit further... which will be a pain if it requires a physical device :( – Jon Skeet Oct 20 '14 at 13:28
  • @JonSkeet I get the MissingManifestResourceException "directly". It's thrown in NodaFormatInfo when it tries to load the resource "OffsetPatternLong" – Markus Bruckner Oct 31 '14 at 14:16
  • Nevermind, just stubled accross http://www.qaster.com/q/520694969783578625/ – Markus Bruckner Oct 31 '14 at 14:19

1 Answers1

3

The workaround by Phil Hoff solved this issue for us. Create the following WindowsRuntimeResourceManager class:

/// <summary>
/// from http://blogs.msdn.com/b/philliphoff/archive/2014/11/19/missingmanifestresourceexception-when-using-portable-class-libraries-in-winrt.aspx
/// </summary>
public class WindowsRuntimeResourceManager : ResourceManager
{
    private readonly ResourceLoader _resourceLoader;

    private WindowsRuntimeResourceManager(string baseName, Assembly assembly)
        : base(baseName, assembly)
    {
        _resourceLoader = ResourceLoader.GetForViewIndependentUse(baseName);
    }

    public static void InjectIntoResxGeneratedApplicationResourcesClass(Type resxGeneratedApplicationResourcesClass)
    {
        resxGeneratedApplicationResourcesClass.GetRuntimeFields()
          .First(m => m.Name == "resourceMan")
          .SetValue(null, new WindowsRuntimeResourceManager(resxGeneratedApplicationResourcesClass.FullName, resxGeneratedApplicationResourcesClass.GetTypeInfo().Assembly));
    }

    public override string GetString(string name, CultureInfo culture)
    {
        return _resourceLoader.GetString(name);
    }
}

Before using NodaTime (e.g., in your App constructor) replace the resource managers of the NodaTime assembly:

        Assembly nodaTimeAssembly = typeof(LocalDate).GetTypeInfo().Assembly;

        Type messagesResource = nodaTimeAssembly.GetType("NodaTime.Properties.Messages");
        Type patternResource = nodaTimeAssembly.GetType("NodaTime.Properties.PatternResources");

        WindowsRuntimeResourceManager.InjectIntoResxGeneratedApplicationResourcesClass(messagesResource);
        WindowsRuntimeResourceManager.InjectIntoResxGeneratedApplicationResourcesClass(patternResource);
Markus Bruckner
  • 2,852
  • 2
  • 24
  • 29