Structuremap config with runtime value ...For<IProductProvider>().Use<ProductProvider>.Ctor<string>("connectionString").Is(someValueAtRunTime);

StackOverflow https://stackoverflow.com/questions/20591737

Question

Structuremap experts,

I found this post on stackoverflow ...

Passing constructor arguments when using StructureMap

Someone suggested to use the StructureMap configuration with runtime value like this

For<IProductProvider>().Use<ProductProvider>.Ctor<string>("connectionString").Is(someValueAtRunTime);

But example is not adequate enough to understand its declaration and usage. I try to find on StructureMap site as well but not much help ...

In my situation, I want to pass on the dependency of concrete DbContext (IDbContext) to the constructor of the class with connection string dynamically created during run time within that class.

Was it helpful?

Solution

Finally I managed to make it working ...

Here how I did it ...

Hope it will help someone, and thanks to PHeiberg for answer me before and showing me right direction.


Interface Definition

public interface ICreditCard
{
    string GetName();
}

public interface IAdditionalCreditCard : ICreditCard
{
}

public class AdditionalCreditCard : IAdditionalCreditCard
{
    private readonly string _name;

    public AdditionalCreditCard(string name)
    {
        _name = name;
    }

    public string GetName()
    {
        return _name;
    }
}

Define function in Structure map config code

Func<string, IAdditionalCreditCard> additionalCreditCard = value =>
  ObjectFactory.With("name").EqualTo(value).GetInstance<AdditionalCreditCard>();

Add following configuration in ObjectFactory.Configure

ObjectFactory.Configure(config =>
{
    config.For<Func<string, IAdditionalCreditCard>>().Use(additionalCreditCard);
});

And in code ...

public class PaymentSystem
{
    private readonly Func<string, IAdditionalCreditCard> _addtionalCreditCard;
    private IAdditionalCreditCard _addCreditCard;

    public PaymentSystem(Func<string, IAdditionalCreditCard> additionalCredit)
    {
        _addtionalCreditCard = additionalCredit;
    }

    public string AddtionalSystemType()
    {
        _addCreditCard = _addtionalCreditCard("American Express");
        return _addCreditCard.GetName();
    }
}

OTHER TIPS

The code you are posting is supposed to go in the setup code for StructureMap, which can go in the Initialize/Configure method or a Registry. The setup code is normally executed only once in the application's life cycle. So if you know the connection string value when the application is stared and you configure StructureMap, you can put the code you posted in the initialization of StructureMap. If the value is not known until later on, you need some kind of factory approach.

A factory approach could be done like this (in your StructureMap configuration code):

Func<string, IDbContext> createContext = value => { 
    /* create context based on value */ 
};
ObjectFactory.Initialize(c => {
    For<Func<string, IDbContext>>().Use(createContext);  
    // The rest of you configuration ...
});

You can now use the Func to create an instance of the context when you need it:

public class ProductProvider : IProductProvider
{
    private readonly Func<string, IDbContext> _contextCreator;
    public ProductProvider(Func<string, IDbContext> contextCreator)
    {
        _contextCreator = contextCreator;
    }

    public IEnumerable<Product> GetProducts(string someValue)
    {
        using(var context = contextCreator(someValue))
        {
            return SomeOperationOnThe(context);
        }
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top