I asked a question previously which had only a single answer. I've had some time to play around with this now and have a plan, but want some feedback on if it is a good idea.
The problem:
I want a component which has a name (invariant, used to identify the component) to have its name localised in the application that is consuming it, without polluting the model of the component with a DisplayName attribute. The component may exist in a separate dll and be dynamically loaded at runtime.
my feeling is that the component dll should be responsible for providing the localised name (this seems like good encapsulation), but the application consuming the component should be responsible for getting/using the localised name (the fact that the component has a different name for display purposes is not a concern of the component, but of the 'view' using that component)
The solution:
Add a resource to the components dll with the same name as the file the component class is in. Add a string to the resource with a key which is the name of the component.
In the application get the localised name like so:
ExternalObject obj = GetExternalObject ();
ResourceManager manager = new ResourceManager (obj.GetType ());
string localisedName= manager.GetString (obj.Name);
This code will probably be encapsulated in a Localiser class, but conveys the point. This seems to work, but is it a good idea, or is there a better/more standard way of doing this?
EDIT: I should point out that one thing that I'm not sure about with this solution is that the resources have to be in a .resx file that has the same name as the file that the class is in. This makes it work, as the resource file can be identified from the type name. This is the same as localisation for forms seems to work, and makes visual studio put the .resx as a 'sub-component' of the .cs file, which all seems nice. But visual studio then throws a warning (about editing a resource that is part of another project item) if I try and edit this file, which makes me think that perhaps there is some other way that I'm supposed to be doing this.
I think you have the right idea, but there's better way to accomplish this.
Presumably, you have an interface that the pluggable component implements. Say, IPluggable:
interface IPluggable {
...
string LocalizedName {get;}
...
}
From your main binary, load the pluggable assembly and create the IPluggable instance using reflection (I assume that's what the GetExternalObject()
method you have does) and then access the localized name using the LocalizedName
property. Inside the IPluggable implementation, create a ResourceManager
and access the LocalizedName
from the resx of that pluggable assembly.
What you get by doing is good encapsulation of behavior in the pluggable assembly - it is responsible for providing you the localized name, however it chooses to do it, without your man program assuming that a ResourceManager
can be created to access a localized name.