Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to pass argument at runtime?

Tags:

c#

lamar

We're migrating from StructureMap to Lamar but I could not find the "Lamar version" for passing arguments at runtime.

We have a class that requires a string argument (pseudo code):

public class MyRepository {
  public MyRepository(string accountId) {}
}

… and a factory

public class MyRepoFactory(Container container) {
  public MyRepository GetRepositoryForAccount(string accountId) => 
     container
        // With() is not available in Lamar?
        .With("accountId").EqualTo(accountId)
        .GetInstance<IMyRepository>();
}

In reality there are additional dependencies.

How can a say Lamar GetInstance() for IMyRepository and use value xy for constructor argument named accountId?

like image 991
Christoph Lütjen Avatar asked Dec 13 '18 13:12

Christoph Lütjen


1 Answers

I see two approaches with Lamar.

Using properties

While Lamar doesn't offer With(), a workaround might be to make the account a property you set in the factory method, or to have the factory simply get all the repository's dependencies manually from the container. It is, after all, a factory, so tying it closely to the type it produces seems fine from a design standpoint.

Using Contexts

A nicer approach might be to set the accountId in a context and use the context in the repository:

public class ExecutionContext
{
    public Guid AccountId { get; set; } = Guid.NewGuid();
}

The repository looks like this

public class MyRepository
{
    public ExecutionContext Context { get; }

    public MyRepository(ExecutionContext context)
    {
        Context = context;
    }
}

Make the context injectable...

var container = new Container(_ =>
{
    _.Injectable<ExecutionContext>();
});

and then, in your factory...

public MyRepository GetRepositoryForAccount(string accountId) {
    var nested = container.GetNestedContainer();
    var context = new ExecutionContext{ AccountId = accountId };
    nested.Inject(context);
    return nested.GetInstance<IMyRepository>()
}

Documentation: https://jasperfx.github.io/lamar/documentation/ioc/injecting-at-runtime/

You also might want to consider if you really need the factory in this scenario, of if using the nested, injectable container directly perhaps makes for a cleaner design.

like image 135
adhominem Avatar answered Oct 07 '22 12:10

adhominem