I have an object:
public class TestEvent : IEvent
{
private string _id;
public TestEvent()
{
}
public TestEvent(string eventId)
{
_id = eventId;
}
}
And I have a StructureMap registry:
public class TheRegistry : Registry
{
public TheRegistry()
{
Scan(_ =>
{
_.TheCallingAssembly();
_.AddAllTypesOf<IEvent>().NameBy(t => t.Name.ToUpper());
});
}
}
I’m trying to get a named instance of IEvent using the StructureMap container and passing in a constructor argument for “eventId”:
var id = "TESTEVENT";
var args = new ExplicitArguments();
args.SetArg("eventId", id);
var eventInstance = _container.GetInstance<IEvent>(args, id);
I think the docs suggest it should work, however I’m getting an ArgumentNullException:
{“Trying to find an Instance of type MyProject.IEvent, MyProject,
Version=1.0.0.0, Culture=neutral, publicKeyToken=null\r\nParameter name: instance”}
All the code works properly if I remove the second constructor, and just grab the named instance.
UPDATE:
Following Kirk’s investigation, I’ve been able to workaround this “issue” by creating a simple object to hold any required arguments. It works now.
public class EventArguments
{
public string EventId { get; set; }
}
...
var eventName = Context.Parameters.EventTypeName.ToString().ToUpper();
var args = new ExplicitArguments();
args.SetArg("args", new EventArguments { EventId = eventName });
var eventInstance = _container.GetInstance<IEvent>(args, eventName);
Full disclosure: I’ve never used StructureMap before, so I could be misunderstanding how it’s intended to be used. But as near as I can tell, either this use-case is intentionally not supported by StructureMap, or it’s a bug.
But first, you have one error; you need to fix your
idto match your.ToUppercall (i.e. it should bevar id = "TESTEVENT";, notvar id = "TestEvent";).Once you’ve done that, though, it still doesn’t work. Inspecting the source code, it’s clear why. The constructor of the types are inspected (in this case,
TestEvent) and if any constructor declares a parameter whose type is “simple” (i.e. primitives, strings, etc.) then that constructor is categorically disqualified from participating in the.GetInstancebehavior.Specifically, if you examine
StructureMap.Graph.PluginFamily.discoverImplicitInstances():It’s that first line in the lambda that is the culprit:
That’s the line that is disqualifying your constructor (and thus your type). Strings can’t be “auto-filled” since you can’t just new one up, and they wouldn’t be registered for injection.
If you comment that line out your code will now work. What puzzles me is that while I understand why your constructor couldn’t be implicitly created, the code as written seems to also disqualify code from working when you are passing explicit arguments as you’ve done.
Maybe someone with more experience with StructureMap will be able to offer more expert guidance, but hopefully this was better than nothing.