Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple constructor with Structuremap changing the scope?

To illustrate the problem, here is a simplified version of my setup. I have a factory like this one :

public interface IFactory{ }

public class Factory : IFactory
{
    public Factory()
    {
        Console.WriteLine("parameterless");
    }

    //public Factory(int i)
    //{
    //    Console.WriteLine("with parameter : {0}", i);
    //}

}

the program to test this is a consoleApp. Enough to prove my point.

static void Main(string[] args)
{
     Init();
     var factory1 = ObjectFactory.GetInstance<IFactory>();
     var factory2 = ObjectFactory.GetInstance<IFactory>();
     var factory3 = ObjectFactory.GetInstance<IFactory>();
     Console.Read();
 }

I setup strucutreMap in my Init static method.

  public static void Init()
        {
            ObjectFactory.Initialize(x =>
            {
                 //insert Initialization code here.
            });
        }

If I have only one constructor and setup StructureMap like this :

x.For<IFactory>().Use<Factory>();

that works perfect, and the output shows
parameterless
parameterless
parameterless

Each call builds a new instance.

Now if I uncomment the second constructor, but I want to use the parameterless one, and with the same default lifestyle. How would I do?

I tried that :

x.SelectConstructor<IFactory>(() => new Factory());
x.For<IFactory>().Use<Factory>();

It just doesn't work : Missing requested Instance property "i" for InstanceKey

If I do like this :

 x.For<IFactory>().Use(new Factory());

It works, but the output is just one "parameterless" meaning it's not building a new instance for each call. It's using this specific instance I pass in.

The only way I found is to add the [DefaultConstructor] on top of my parameterless constructor and use the standard x.For().Use(); But I don't want to add this attribute and spread the configuration accross my model.

Help?

like image 425
Stéphane Avatar asked Jan 22 '23 12:01

Stéphane


1 Answers

SelectConstructor takes the concrete type, not the interface. Of course, an interface doesnt have any constructor. But nothing breaks, it's just ignored.... so I couldnt spot that error.

 x.SelectConstructor<IFactory>(() => new Factory());
 x.For<IFactory>().Use<Factory>();

should be

 x.SelectConstructor<**Factory**>(() => new Factory());
 x.For<IFactory>().Use<Factory>();
like image 136
Stéphane Avatar answered Mar 15 '23 19:03

Stéphane