将构造函数args传递给StructureMap命名实例时出错

时间:2012-10-23 16:17:57

标签: c# inversion-of-control structuremap

我有一个对象:

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);

1 个答案:

答案 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有更多经验的人能够提供更多专家指导,但希望这比没有好。