Using ResourceManger with a CustomAssembly
ResourceMangers provide convenient access to culture-specific resources at run time. Resources may reside in the current or external assemblies. A ResourceManager can be created by specifying the base name of the resource file and assembly where it resides. However one constraint it not documented, the provided assembly must be of the type “ RuntimeAssembly” (not public). While most of the time you will, without knowing, be dealing with RuntimeAssemblies it is possible to end up with System.Reflection.Context.Custom.CustomAssembly instead which is not a RuntimeAssembly. The trouble begins…
|
|
Example of the error
This post is written for .NET framework 4.8
, although it applies to the latest version as well (.NET 5
).
Problem at hand
There are many ways to get hold of the assembly to pass to the ResourceManger, one way is to use the Assembly property on Type. When using CustomReflectionContext, which allows one to add custom attributes to existing types, one may end up with a System.Reflection.Context.Custom.CustomType. Its Assembly property will return a System.Reflection.Context.Custom.CustomAssembly, which as noted before is not compatible with the ResourceManger. ReflectionContext can be used in many .NET reflection API’s and e.g. in MEF.
The constraint on using a RuntimeAssembly is nowhere documented, but the code, and if attempted will result in a System.ArgumentException: “Assembly must be a runtime Assembly object.”. For those who were not aware, Assembly is an abstract class which has multiple implementations where not all implementations are equal ;)1
Workaround
While one could obtain the Assembly in another way, e.g. Assembly.LoadFile(path) or for the current Assembly Assembly.GetExecutingAssembly(), sometimes that is not an option.
Another solution is to convert the CustomType to a RuntimeType (which has a RuntimeAssembly) which is surprisingly easy.
|
|
Solution to convert a CustomType to a RuntimeType
Both CustomAssembly and RuntimeAssembly are internal classed, hence no proper client-side logic can be implemented to handle them differently, fortunately the workaround above always works.
This breaks the Abstraction principle in Object Oriented programming. Resulting in exceptions upon correct usage of the API as described in this post. ↩︎
- Permalink: //oostens.me/posts/using-resourcemanger-with-a-customassembly/
- License: The text and content is licensed under CC BY-NC-SA 4.0. All source code I wrote on this page is licensed under The Unlicense; do as you please, I'm not liable nor provide warranty.