question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Passing parameter to ctor while having other parameters auto-resolved?

See original GitHub issue

Hi,

I have a (potentially strange) requirement in which I’d really like to be able to use the container to create a class that contains multiple ctor parameters while auto-resolving all parameters except also allow for specifying the value of potentially one or more at resolution time.

As an example let’s say I have this class structure and I want to be able to specify the string value when I resolve IFoo, but I would like IBar1 and IBar2 to be auto-resolved:

public interface IFoo
{
}
public interface IBar1
{
}
public interface IBar2
{
}

public class Foo : IFoo
{
    public Foo(string value, IBar1 bar1, IBar2 bar2)
    {

    }
}

I have reviewed the answer on SO here on how to achieve this: http://stackoverflow.com/questions/21785822/simple-injector-or-lightinject-pass-parameters-to-constructor?answertab=votes#tab-top

Which works, but this would mean that I would have to code the ctor for each instance I require whereas it’d be fantastic if the container could somehow still auto-resolve all of the parameters apart from the string.

Is there any way to achieve this?

Issue Analytics

  • State:closed
  • Created 8 years ago
  • Comments:10 (5 by maintainers)

github_iconTop GitHub Comments

1reaction
seesharpercommented, Dec 21, 2015

I think I have found a solution for you.

If fact, LightInject “almost” supported this out of the box and only minor brain surgery was needed to make this happen.

Let’s first take a look at the following unit test created for the sole purpose of this issue.

public void ShouldAutoResolveRemainingArguments()
{
    var container = CreateContainer();
    container.Register<IBar1,Bar1>();
    container.Register<IBar2, Bar2>();
    container.Register<IFoo, Foo>();               

    container.RegisterConstructorDependency((factory, info, runtimeArguments) => (string)(runtimeArguments[0]));                               
    var firstInstance = container.GetInstance<string,IFoo>("SomeValue");
    var secondInstance = container.GetInstance<string, IFoo>("AnotherValue");

    Assert.Equal("SomeValue", ((Foo)firstInstance).Value);
    Assert.Equal("AnotherValue", ((Foo)secondInstance).Value);
}

The RegisterConstructorDependency method has gotten an new overload that passes the runtime arguments supplied to the GetInstance method. This means that you can reason about the constructor parameter such as its type, declaring type and so on and then decide if you should fulfill the dependency using the given runtime argument. The rest of the dependencies are resolved as usual and you no longer need to be so explicit about the constructor dependencies even when using runtime arguments.

A new version of LightInject (4.0.3) has just been published to the official NuGet feed containing this new feature.

For reference here is the sample classes used in the test.

    public interface IFoo
    {
    }
    public interface IBar1
    {
    }
    public interface IBar2
    {
    }

    public class Bar1 : IBar1
    {

    }

    public class Bar2 : IBar2 
    {

    }

    public class Foo : IFoo
    {
        public string Value { get; private set; }
        public IBar1 Bar1 { get; private set; }
        public IBar2 Bar2 { get; private set; }

        public Foo(string value, IBar1 bar1, IBar2 bar2)
        {
            Value = value;
            Bar1 = bar1;
            Bar2 = bar2;
        }
    }
1reaction
seesharpercommented, Dec 20, 2015

There is always a way to solve anything 😃

So you have something like this

var container = new ServiceContainer();
container.Register<IBar1,Bar1>();
container.Register<IBar2, Bar2>();

container.Register<string, IFoo>(
    (factory, s) => new Foo(s, factory.GetInstance<IBar1>(), factory.GetInstance<IBar2>()));

var instance = container.GetInstance<string, IFoo>("SomeString");

What we could do here is scan for a certain pattern in the constructor of the target types and one such pattern could be that the first argument is a string and then we invoke the appropriate Register method such that when the GetInstance method is invoked with a string runtime argument, it would work as if you have explicitly registered the constructor.

What do you think? Would that be something that could work?

Read more comments on GitHub >

github_iconTop Results From Across the Web

NET Core DI, ways of passing parameters to constructor
The expression parameter (x in this case) of the factory delegate is an IServiceProvider . Use that to resolve the dependencies:
Read more >
Is passing arguments to a constructor always considered DI?
If I pass this object to that constructor, does that new object now have a dependency? Nope. Just 'cause you pass it, that...
Read more >
3.1.9. Auto-Resolution Of Constructor Parameters
If the parameter is typehinted to a class but there is no $di->params value for that parameter, and also no default value, the...
Read more >
Passing constructor parameters in xaml file - Microsoft Q&A
I would like to know how to pass constructor parameters in a xaml file? Example: NewChart.cs public partial class NewChart : UserControl ...
Read more >
Passing Parameters to Resolve - Autofac's documentation!
ResolvedParameter can be used as a way to supply values dynamically retrieved from the container, e.g. by resolving a service by name. Parameters...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found