Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

No all resources updated #23

Closed
hubert-wojtowicz opened this issue May 7, 2019 · 5 comments

Comments

@hubert-wojtowicz
Copy link

commented May 7, 2019

Hello,
I encountered that:
IEnumerable<Assembly> TypeDiscoveryHelper.GetAssemblies(Func<Assembly, bool> assemblyFilter)
does not load all assemblies due to line:
var allAssemblies = AppDomain.CurrentDomain.GetAssemblies();
what cause not all resources are updated.
Loading all assemblies strategy is presented here.
@valdisiljuconoks, do you think @3dave answer on stackoverflow can be applied in library?

@valdisiljuconoks

This comment has been minimized.

Copy link
Owner

commented May 7, 2019

hm, yes of course..

can you describe your context? what's your setup?

@hubert-wojtowicz

This comment has been minimized.

Copy link
Author

commented May 7, 2019

I register localization-provider-core in .net core 2.2 WebAPI project. I have one direct reference (class library .net core 2.2) which contains plain object decorated with [LocalizedResource] resources.

After starting application this resource is not registered.

When I hit breakpoint with line (added intentionally for debugging purpose):
var allAssemblies = AppDomain.CurrentDomain.GetAssemblies();
in my Startup.cs in ConfigureServices method, one line before provider registration:
services.AddDbLocalizationProvider(cfg =>...
there is no expected assembly (that contains resource).

If you need some more information please let me know.

@valdisiljuconoks

This comment has been minimized.

Copy link
Owner

commented May 7, 2019

provided solution on SO is not 100% reliable. for example, you might be referencing assembly, but none of the types are using in your app. assembly linker might come up with decision not to write that assembly in referenced assembly list. thus - you will not get that assembly.
one of the workaround I see here is to include at least one resource from that assembly as "foreign" resource description. that should make it sure that assembly is included in current appdomain.

services.AddDbLocalizationProvider(_ =>
{
    _.ForeignResources.Add<MyForeignAssembly.Namespace.ResourceClassToInclude>();
});
@hubert-wojtowicz

This comment has been minimized.

Copy link
Author

commented May 7, 2019

assembly linker might come up with decision not to write that assembly in referenced assembly list.

I believe if all types in referenced assembly are not used it is not an issue - it is even good. When they will be used they will be taken into account and registered. Correct me if I am wrong.

Here is example implementation that I thought about (inspired by stackoverflow example I mentioned before):

    public static class AssembliesHelper
    {
        /// <summary>
        /// Load all assemblies by walking through all assembly references.
        /// </summary>
        /// <param name="filter">Filter applied to all assembly references.</param>
        /// <returns>All found assemblies.</returns>
        public static IEnumerable<Assembly> LoadAllAsseblies(Func<AssemblyName, bool> filter = null)
        {
            if (filter == null)
                filter = x => true;

            var list = new List<string>();
            var stack = new Stack<Assembly>();

            stack.Push(Assembly.GetEntryAssembly());

            do
            {
                var asm = stack.Pop();

                yield return asm;

                foreach (var reference in asm.GetReferencedAssemblies().Where(filter))
                    if (!list.Contains(reference.FullName))
                    {
                        stack.Push(Assembly.Load(reference));
                        list.Add(reference.FullName);
                    }

            }
            while (stack.Count > 0);
        }
    }

Then I would swap line in method TypeDiscoveryHelper.GetAssemblies:
var allAssemblies = AppDomain.CurrentDomain.GetAssemblies();
with
var allAssemblies = AssembliesHelper.LoadAllAsseblies().ToList();

@valdisiljuconoks

This comment has been minimized.

Copy link
Owner

commented May 8, 2019

yes, this is planned implementation. just was referring that it's not 100% reliable (if linker skips referenced assembly). I would need to add this as optional switch IMHO as it might have performance implications on startup.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
2 participants
You can’t perform that action at this time.