我有一个对象:
public class TestEvent : IEvent
{
private string _id;
public TestEvent()
{
}
public TestEvent(string eventId)
{
_id = eventId;
}
}
我有一个StructureMap注册表:
public class TheRegistry : Registry
{
public TheRegistry()
{
Scan(_ =>
{
_.TheCallingAssembly();
_.AddAllTypesOf<IEvent>().NameBy(t => t.Name.ToUpper());
});
}
}
我正在尝试使用StructureMap容器获取IEvent的命名实例,并为“eventId”传递构造函数参数:
var id = "TESTEVENT";
var args = new ExplicitArguments();
args.SetArg("eventId", id);
var eventInstance = _container.GetInstance<IEvent>(args, id);
我认为文档建议它应该有效,但是我得到了一个ArgumentNullException:
{“试图找到MyProject.IEvent类型的实例,MyProject, Version = 1.0.0.0,Culture = neutral,publicKeyToken = null \ r \ nParameter name:instance“}
如果删除第二个构造函数,只需抓取命名实例,所有代码都能正常工作。
更新
在Kirk的调查之后,我已经能够通过创建一个包含任何必需参数的简单对象来解决这个“问题”。它现在有效。
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);
答案 0 :(得分:1)
完全披露:我之前从未使用过StructureMap,所以我可能会误解它是如何被使用的。但就我所知,这个用例有意不被StructureMap支持,或者它是一个bug。
但首先,你有一个错误;您需要修正id
以匹配.ToUpper
来电(即var id = "TESTEVENT";
,而不是var id = "TestEvent";
)。
但是,一旦你完成了它,它仍然无效。检查源代码,很明显为什么。检查类型的构造函数(在本例中为TestEvent
),如果任何构造函数声明了一个类型为“simple”的参数(即基元,字符串等),则该构造函数被明确取消参与.GetInstance
行为。
具体来说,如果您检查StructureMap.Graph.PluginFamily.discoverImplicitInstances()
:
private void discoverImplicitInstances()
{
_pluggedTypes.Each((key, plugin) =>
{
if (!plugin.CanBeAutoFilled) return;
if (hasInstanceWithPluggedType(plugin)) return;
ConfiguredInstance instance = new ConfiguredInstance(plugin.PluggedType).WithName(key);
FillInstance(instance);
});
}
这是lambda中的第一行是罪魁祸首:
if (!plugin.CanBeAutoFilled) return;
这就是取消你的构造函数(以及你的类型)的行。字符串不能“自动填充”,因为你不能只是新的,并且它们不会注册注射。
如果您评论该行,您的代码现在可以正常工作。让我感到困惑的是,虽然我理解为什么你的构造函数不能隐式地创建,但是当你传递显式参数时,所写的代码似乎也取消了代码的工作资格。你做完了。
也许对StructureMap有更多经验的人能够提供更多专家指导,但希望这比没有好。