Skip to content

Import Keyed injects wrong instance #181

Description

@scovel

Multiple Keyed (Named?) Instances. Constructor wants a specific key. Grace injects the wrong instance. Am I doing something wrong? See //returns Mongo below...

.Net Core (NetStandar 2.0)
Grace 6.4.0

using System;
using Grace.DependencyInjection;
using Grace.DependencyInjection.Attributes;

namespace test
{
class Program
{
static void Main(string[] args)
{
DatabaseFactory SqlServer = new DatabaseFactory() {name = "SqlServer"};
DatabaseFactory Oracle = new DatabaseFactory() {name = "Oracle"};
DatabaseFactory Mongo = new DatabaseFactory() {name = "Mongo"};

        var container = new DependencyInjectionContainer();
        container.Configure(c =>
        {
            c.ExportInstance(SqlServer).As<IDatabaseFactory>().AsKeyed<IDatabaseFactory>(SqlServer.name);
            c.ExportInstance(Oracle).As<IDatabaseFactory>().AsKeyed<IDatabaseFactory>(Oracle.name);
            c.ExportInstance(Mongo).As<IDatabaseFactory>().AsKeyed<IDatabaseFactory>(Mongo.name);
            c.Export<TestDal>().As<ITestDal>();
        });

        IDatabaseFactory dbFactory = container.Locate<IDatabaseFactory>(withKey: "SqlServer");
        if (dbFactory.name != "SqlServer") //works
            throw new Exception("wrong dbFactory");


        var testDal = container.Locate<ITestDal>();

        if (testDal.DatabaseFactory.name != "SqlServer") //returns Mongo
            throw new Exception("wrong database in Dal");

    }
}

public interface IDatabaseFactory
{
    string name { get; set; }
}

public class DatabaseFactory : IDatabaseFactory
{
    public string name { get; set; }
}

public interface ITestDal
{
    IDatabaseFactory DatabaseFactory { get; }
}

public class TestDal : ITestDal
{
    private IDatabaseFactory _databaseFactory;

    public TestDal([Import(Key = "SqlServer")] IDatabaseFactory techXpress)
    {
        _databaseFactory = techXpress;
    }

    public IDatabaseFactory DatabaseFactory
    {
        get { return _databaseFactory; }
    }
}

}

Activity

  1. ipjohnson commented on Aug 1, 2018

    @ipjohnson
    Owner

    Hi @scovel

    The reason it's returning the mongo is instance is because it's not actually processing the import attribute and picking the last registered instance of IDatabaseFactory. This could be argued to be a bug because it seems like it should throw an export not found rather than picking a keyed export. I'm hesitant to change the behavior in a non major release because even though it's not technically correct it seems like a major behavior shift to introduce in a minor version release.

    The assumption I made when creating the container is that people would use either the fluent interface or the attributes for configuration. I hadn't thought of the idea of using fluent for part of the registration and attributes for the other.

    That said you're the second person recently that ran into problems with this exact use case. I think maybe the answer is to add a flag to force the container to process Import attributes on parameters even when doing fluent validation.

  2. scovel commented on Aug 1, 2018

    @scovel
    Author
  3. ipjohnson commented on Aug 1, 2018

    @ipjohnson
    Owner

    @scovel for the moment I think it's much easier to make a slight change to the fluent registration to specify the key than set up registration using attributes.

    c.Export<TestDal>().As<ITestDal>().WithCtorParam<IDatabaseFactory>().LocateWithKey("SqlServer");

    I'll see if I can find some time this weekend to add the flag as it's shouldn't much work and I'll release a beta for you to try.

    That's very cool about your son, very good name :)

  4. scovel commented on Aug 1, 2018

    @scovel
    Author
  5. ipjohnson commented on Aug 1, 2018

    @ipjohnson
    Owner

    That makes complete sense. I’ll write a more in depth reply this evening but the short version is I’ll add a flag to process the import attribute automatically and it should solve your issue.

  6. scovel commented on Aug 1, 2018

    @scovel
    Author
  7. ipjohnson commented on Aug 3, 2018

    @ipjohnson
    Owner

    @scovel I've added a flag to process import attributes on constructor parameters. I set it to true by default because it seems like if you went the length to attach an attribute you want it processed.

    Would it be possible for you to test it off the nightly nuget feed? I'd prefer to test it before I release an RC to nuget.org.

    https://ci.appveyor.com/nuget/grace-master

  8. scovel commented on Aug 3, 2018

    @scovel
    Author
  9. ipjohnson commented on Aug 3, 2018

    @ipjohnson
    Owner

    @scovel one thing I did realize when I was working this is that your registration should be tweaked a little.

    I think you want

    c.ExportInstance(SqlServer).AsKeyed<IDatabaseFactory>(SqlServer.name);

    I don't think you want the extra As<IDatabaseFactory> , I think you want only the keyed export.

  10. scovel commented on Aug 3, 2018

    @scovel
    Author
  11. scovel commented on Aug 3, 2018

    @scovel
    Author
  12. ipjohnson commented on Aug 3, 2018

    @ipjohnson
    Owner

    @scovel I'll push an RC to nuget this weekend and plan to do an official release later this month

  13. ipjohnson commented on Aug 6, 2018

    @ipjohnson
    Owner

    I released an RC version today

  14. scovel commented on Aug 14, 2018

    @scovel
    Author
  15. ipjohnson commented on Aug 16, 2018

    @ipjohnson
    Owner

    @scovel sorry had to publish another preview for another issue. I'm shooting for middle of next week for an official release.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions