JasperFx / lamar

Fast Inversion of Control Tool and Successor to StructureMap
https://jasperfx.github.io/lamar
MIT License
563 stars 118 forks source link

NameBy not executed for AddAllTypesOf when type is open generic #307

Closed firedog closed 2 years ago

firedog commented 2 years ago

Don't know if this is supposed to be a valid use case or not but when I'm registering types for an open generic interface using AddAllTypesOf and trying to name them using NameBy they will still get what seems to be a default name set by Lamar.

When a non-generic interface is used the NameBy method works as expected.

Sample Console app reproducing the issue:

using System;
using Lamar;

namespace LamarTest
{
    public interface IThing
    { }
    public interface IOtherThing<T>
    { }
    public class FirstThing : IThing
    { }
    public class SecondThing : IThing
    { }
    public class FirstOtherThing : IOtherThing<string>
    { }
    public class SecondOtherThing : IOtherThing<int>
    { }

    class Program
    {

        static void Main(string[] args)
        {

            var container = new Container(x =>
            {
                x.Scan(_ =>
                {
                    _.AssemblyContainingType<IThing>();
                    _.WithDefaultConventions();

                    _.AddAllTypesOf(typeof(IThing)).NameBy(t => t.Name.ToUpper());

                    _.AddAllTypesOf(typeof(IOtherThing<>)).NameBy(t => t.Name.ToUpper());
                });
            });

            var have = container.WhatDoIHave();
            Console.WriteLine(have);
            Console.WriteLine();

            var name = "FIRSTTHING";
            WriteObject(container.TryGetInstance<IThing>(name), name);

            name = "SECONDOTHERTHING";
            WriteObject(container.TryGetInstance<IOtherThing<int>>(name), name);

            name = "secondOtherThing";
            WriteObject(container.TryGetInstance<IOtherThing<int>>(name), name);

            Console.WriteLine("\nPress ENTER to exit");
            Console.ReadLine();
        }

        private static void WriteObject(object o, string name)
        {
            Console.WriteLine(o == null
                ? $"Failed resolving object by name {name}"
                : $"Successfully resolved object by name {name}. Declaring type is {o.GetType().Name}");
            Console.WriteLine();
        }
    }
}

Sample app output:

=========================================================================================================================================
ServiceType              Namespace                                    Lifecycle     Description                      Name
-----------------------------------------------------------------------------------------------------------------------------------------
IContainer               Lamar                                        Scoped        Current IContainer               IContainer
-----------------------------------------------------------------------------------------------------------------------------------------
IOtherThing<string>      LamarTest                                    Transient     new FirstOtherThing()            firstOtherThing
-----------------------------------------------------------------------------------------------------------------------------------------
IOtherThing<int>         LamarTest                                    Transient     new SecondOtherThing()           secondOtherThing
-----------------------------------------------------------------------------------------------------------------------------------------
IServiceContext          Lamar                                        Scoped        Current IServiceContext          IServiceContext
-----------------------------------------------------------------------------------------------------------------------------------------
IServiceProvider         System                                       Scoped        Current IServiceProvider         IServiceProvider
-----------------------------------------------------------------------------------------------------------------------------------------
IServiceScopeFactory     Microsoft.Extensions.DependencyInjection     Singleton     Current IServiceScopeFactory     IServiceScopeFactory
-----------------------------------------------------------------------------------------------------------------------------------------
IThing                   LamarTest                                    Transient     new FirstThing()                 FIRSTTHING
                                                                      Transient     new SecondThing()                SECONDTHING
-----------------------------------------------------------------------------------------------------------------------------------------
Scope                    Lamar.IoC                                    Scoped        Current Scope                    Scope
=========================================================================================================================================

Successfully resolved object by name FIRSTTHING. Declaring type is FirstThing

Failed resolving object by name SECONDOTHERTHING

Successfully resolved object by name secondOtherThing. Declaring type is SecondOtherThing

Press ENTER to exit
jeremydmiller commented 2 years ago

@firedog Sorry for being so slow here. Yeah, no. The lazy "open to closed type" resolution is just a different animal altogether. I think this is going to be an "I take pull requests" if this is really important to you. You'd need to change the GenericConnectionScanner" to apply a naming policy as well, then connect that throughFindAllTypesFilter`

firedog commented 2 years ago

No worries, I can work around it in a few different ways...thanks for the reply!

Maybe a note in the documentation could help future users?