locked
ResourceManager GetResourceSet locks resource Satellite assembly RRS feed

  • Question

  • Hi,

    I have created a WPF application for translating .Net Desktop application (WPF and Forms).

    I load all resources from the executable file the user selectes. I then load the key and value from the default resources and display them in a DataGrid. I also display the values for the culture the user have selected (If any exists). Problem is when the Culture exists the ResourceManager loads the values from the satellite assembly but never releases the fileHandle for the Satellite assembly.


    private void LoadResources()
            {
                _resourceEntries.Clear();
                var assembly = Assembly.LoadFrom(_selectedExecutableFile.FullName);
    
                // Create the new application domain.
                var domain = AppDomain.CreateDomain("MyDomain", assembly.Evidence);
    
                var resourceNames = assembly.GetManifestResourceNames();
    
                foreach (var resourceName in resourceNames)
                {
                    var resourceManager = new ResourceManager(resourceName.Replace(".resources", ""), assembly);
                    var invariantCultureResourceSet = resourceManager.GetResourceSet(CultureInfo.InvariantCulture, true, true);
    
                    using (var translateCultureResourceSet = resourceManager.GetResourceSet(PossibleLanguages.SelectedItem as CultureInfo, true, false))
                    {
                        var resourceSetEnumerator = invariantCultureResourceSet.GetEnumerator();
    
                        while (resourceSetEnumerator.MoveNext())
                        {
                            var name = resourceSetEnumerator.Key as string;
                            var value = resourceSetEnumerator.Value;
    
                            //Only translate strings
                            if (!(value is string))
                                continue;
    
                            var translatedValue = (translateCultureResourceSet == null) ? "" : translateCultureResourceSet.GetString(name);
    
                            _resourceEntries.Add(new ResourceEntry(resourceName, name, value as string, translatedValue));
                        }
                        if (translateCultureResourceSet != null)
                        {
                            translateCultureResourceSet.Dispose();
                            translateCultureResourceSet.Close();
                        }
                        resourceManager.ReleaseAllResources();
                    }
                }
                AppDomain.Unload(domain);
                ResourceGrid.ItemsSource = _resourceEntries;
            }


    The call to GetResourceSet locks the resource Satellite assembly, problem with this is i want to use the Assembly Linker to overwrite the existing Culture. But i cannot seem to release the FileHandle without closing the Translation application.

    var translateCultureResourceSet = resourceManager.GetResourceSet(PossibleLanguages.SelectedItem as CultureInfo, true, false)

    I have tried calling close and dispose on the resourceSet. I have also called ReleaseAllResources on the ResourceManager.

    And as MSDN states in documentation for ReleaseAllResources, this function does not work for Satellite assemblies, so i have also tried to create a AppDomain and unload this after loading resources.

    I am running out of ideas to try, and would greatly appreciate any thoughs on the issues. If i could load the selected culture in an different way, or a workaround to remove the fileHandle. Anything would be great just need to get this project closed asap.

    Regards,

    Anders


    Thursday, March 6, 2014 9:10 AM

Answers

  • So.... The solution was a AppDomain, guess i just had to little experience with AppDomains.

    Created appDomain like so:

                var newDomain = AppDomain.CreateDomain("LoadResourceDomain");
                var demoProcessor = (ResourcesLoader)newDomain.CreateInstanceAndUnwrap(Assembly.GetExecutingAssembly().FullName, typeof(ResourcesLoader).FullName);
    
                _resourceEntries = demoProcessor.LoadResources(_selectedExecutableFile, PossibleLanguages.SelectedItem as CultureInfo);
                ResourceGrid.ItemsSource = _resourceEntries;
    
                AppDomain.Unload(newDomain);

    Where ResourceLoader is a Class which inherits from MarshalByRefObject, and contains my previous posted "LoadResources" methods.

    Also had to make ResourceEntry class Serializable.

    And voila.... success ;)

    • Marked as answer by AjesLind Thursday, March 6, 2014 12:41 PM
    Thursday, March 6, 2014 12:41 PM