Rockford Lhotka's Blog

Home | Lhotka.net | CSLA .NET

 Monday, 25 July 2016

I have an existing .NET project (CSLA .NET) that uses resx resource files for localization. While adding support to CSLA .NET for .NET Core I had to figure out how to use resx files in a .NET Core (NetStandard 1.5) Class Library.

There is a doc for .NET Core Globalization and Localization that has good info, but it did lead me down a bad road given that I’m bringing in existing code and resx files.

There’s not currently tooling in Visual Studio 2015 for dealing with resources in .NET Core projects, or at least not like you’d expect from VS with full .NET. But there’s enough tooling that if you copy or create a Resources.resx file in a folder of your project you’ll end up with the appropriate generated designer.cs file.

Note that the Microsoft doc says that they think most of us won’t use that generated file. I think they are full of crap, because the alternative is to not use strongly typed access to your resources, and to manually craft a class to access your resources. WTF!?! So I’m ignoring their non-recommendation/supposition that I think is completely wrong, and I’m continuing to rely on the designer.cs file that has provided so much value since 2002.

The problem I encountered is that in the Microsoft doc they talk about putting your resx file(s) into a Resources folder. DO NOT DO THIS.

The tooling that generates the designer.cs file uses the folder name to create the namespace for the generated code. If you use a Resources folder the resulting name (for me) was Csla.Resources. And the class they generate is named Resources. So you have a class named ‘Csla.Resources.Resources’ – and it is a static class. As a result you basically can’t access any of the properties or methods in the class without using the full type name (no using statements allowed)!! It is a total mess.

SO DO NOT NAME YOUR FOLDER ‘Resources’!!

A related problem flows from the fact that I’m using existing code, all of which assumes the resx files are in the ‘Properties’ folder, so the namespace is ‘Csla.Properties’. So really what I need is to have all my resx files in the ‘Properties’ folder within my project so the full type name of the generated code is ‘Csla.Properties.Resources’ just like it has been in .NET projects for years and years and years.

The resx code generation tool appears to only run if the Resources.resx file is really in that folder (not linked from elsewhere), so I needed a way to copy my resx file from its original location into my NetStandard project.json:

"scripts": {     "precompile": "copyResources.cmd"
},

And of course this means that I also have that cmd file in my project’s root folder (a peer with project.json):

del Properties\*.resx
copy ..\Csla.Shared.Resources\*.resx Properties\

Notice how I’m deleting and recopying the files on every build. This is because the master source for my resx files is in the ‘Csla.Shared.Resources’ folder, and I don’t want anyone thinking they can edit the resx file in this copy – that’d be a maintenance issue! (as an aside, I also added these copied resx files to my .gitignore file so they never get checked into source control – they are just a build artifact after all)

As soon as the Resources.resx file is copied into the folder the designer.cs file is created, which means all my code that has ‘using Csla.Properties;’ and that uses the strongly typed members from the ‘Resources’ class will all work.

However, it is also critical that the resx files be leveraged as embedded resources when the project builds. To make this happen I had to add more lines to the project.json file:

"buildOptions": {     "compile": [ "../Csla.Shared/**/*.cs" ],
    "embed": {         "include": [ "Properties/Resources.resx" ]     },
    "define": [ "NETFX_CORE", "NETCORE", "NETSTANDARD" ],     "outputName": "Csla",     "xmlDoc": true
},

The “embed” build option indicates that the Resources.resx file should be embedded as a resource in the compiled DLL from the project. All the other localized resx files are automatically picked up and used to create satellite assemblies just like in full .NET. The result is that my build output directory contains ‘Csla.dll’ with the default resources embedded, and satellite assemblies in per-culture folders as you’d expect.

snip_20160725134541

To summarize:

  1. Do not put your Resources.resx file into a Resources folder – that way lies madness
  2. If porting existing code to .NET Core you’ll almost certainly want to put the resx files into your ‘Properties’ folder to get the same namespace as full .NET
  3. If porting existing code, use a precompile directive to copy the resource files to the target location
  4. Use the “embed” build option to embed your Resources.resx file into your assembly to make the default culture available
Monday, 25 July 2016 12:48:20 (Central Standard Time, UTC-06:00)  #    Disclaimer
 Friday, 22 July 2016

I am thrilled with the “Your Groove” functionality in the Groove music app.

Years ago I begged and pleaded to get Pandora-like functionality in the (then) Zune app. Microsoft responded with SmartDJ, which later became Radio – and that has been excellent all these years – and I still use that functionality a lot.

However, this new “My Groove” feature adds a new dimension to the overall experience that I really like a lot. For example:

msohtmlclipclip_image001

The Radio feature sometimes provides new music, but dynamic channels like this one provide a lot of new music. And they auto-update weekly, so they never get stale.

I’m at the point where I think I’ll cancel my SiriusXM subscription in my car, because I can just sync these playlists to my phone and play them via BlueTooth – who needs SXM Octane to find new music when Groove does a better job for a lot less money!

Friday, 22 July 2016 13:22:53 (Central Standard Time, UTC-06:00)  #    Disclaimer
On this page....
Search
Archives
Feed your aggregator (RSS 2.0)
February, 2017 (2)
January, 2017 (2)
December, 2016 (5)
November, 2016 (2)
August, 2016 (4)
July, 2016 (2)
June, 2016 (4)
May, 2016 (3)
April, 2016 (4)
March, 2016 (1)
February, 2016 (7)
January, 2016 (4)
December, 2015 (4)
November, 2015 (2)
October, 2015 (2)
September, 2015 (3)
August, 2015 (3)
July, 2015 (2)
June, 2015 (2)
May, 2015 (1)
February, 2015 (1)
January, 2015 (1)
October, 2014 (1)
August, 2014 (2)
July, 2014 (3)
June, 2014 (4)
May, 2014 (2)
April, 2014 (6)
March, 2014 (4)
February, 2014 (4)
January, 2014 (2)
December, 2013 (3)
October, 2013 (3)
August, 2013 (5)
July, 2013 (2)
May, 2013 (3)
April, 2013 (2)
March, 2013 (3)
February, 2013 (7)
January, 2013 (4)
December, 2012 (3)
November, 2012 (3)
October, 2012 (7)
September, 2012 (1)
August, 2012 (4)
July, 2012 (3)
June, 2012 (5)
May, 2012 (4)
April, 2012 (6)
March, 2012 (10)
February, 2012 (2)
January, 2012 (2)
December, 2011 (4)
November, 2011 (6)
October, 2011 (14)
September, 2011 (5)
August, 2011 (3)
June, 2011 (2)
May, 2011 (1)
April, 2011 (3)
March, 2011 (6)
February, 2011 (3)
January, 2011 (6)
December, 2010 (3)
November, 2010 (8)
October, 2010 (6)
September, 2010 (6)
August, 2010 (7)
July, 2010 (8)
June, 2010 (6)
May, 2010 (8)
April, 2010 (13)
March, 2010 (7)
February, 2010 (5)
January, 2010 (9)
December, 2009 (6)
November, 2009 (8)
October, 2009 (11)
September, 2009 (5)
August, 2009 (5)
July, 2009 (10)
June, 2009 (5)
May, 2009 (7)
April, 2009 (7)
March, 2009 (11)
February, 2009 (6)
January, 2009 (9)
December, 2008 (5)
November, 2008 (4)
October, 2008 (7)
September, 2008 (8)
August, 2008 (11)
July, 2008 (11)
June, 2008 (10)
May, 2008 (6)
April, 2008 (8)
March, 2008 (9)
February, 2008 (6)
January, 2008 (6)
December, 2007 (6)
November, 2007 (9)
October, 2007 (7)
September, 2007 (5)
August, 2007 (8)
July, 2007 (6)
June, 2007 (8)
May, 2007 (7)
April, 2007 (9)
March, 2007 (8)
February, 2007 (5)
January, 2007 (9)
December, 2006 (4)
November, 2006 (3)
October, 2006 (4)
September, 2006 (9)
August, 2006 (4)
July, 2006 (9)
June, 2006 (4)
May, 2006 (10)
April, 2006 (4)
March, 2006 (11)
February, 2006 (3)
January, 2006 (13)
December, 2005 (6)
November, 2005 (7)
October, 2005 (4)
September, 2005 (9)
August, 2005 (6)
July, 2005 (7)
June, 2005 (5)
May, 2005 (4)
April, 2005 (7)
March, 2005 (16)
February, 2005 (17)
January, 2005 (17)
December, 2004 (13)
November, 2004 (7)
October, 2004 (14)
September, 2004 (11)
August, 2004 (7)
July, 2004 (3)
June, 2004 (6)
May, 2004 (3)
April, 2004 (2)
March, 2004 (1)
February, 2004 (5)
Categories
About

Powered by: newtelligence dasBlog 2.0.7226.0

Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

© Copyright 2017, Marimer LLC

Send mail to the author(s) E-mail



Sign In