如何在运行时传递参数?

5
我们正在从StructureMap迁移到Lamar,但我找不到“Lamar版本”以便在运行时传递参数。
我们有一个需要字符串参数(伪代码)的类:
public class MyRepository {
  public MyRepository(string accountId) {}
}

...和工厂

public class MyRepoFactory(Container container) {
  public MyRepository GetRepositoryForAccount(string accountId) => 
     container
        // With() is not available in Lamar?
        .With("accountId").EqualTo(accountId)
        .GetInstance<IMyRepository>();
}

实际上还有其他依赖关系。

如何说Lamar使用IMyRepositoryGetInstance()方法,并为构造函数参数accountId使用值xy?

2个回答

2

我看到Lamar有两种方法。

使用属性

虽然Lamar没有提供With(),但一个解决方法可能是将账户设置为工厂方法中设置的属性,或者让工厂直接从容器中手动获取所有存储库的依赖项。毕竟,它是一个工厂,因此将其与生成的类型紧密联系在一起从设计上看似乎没问题。

使用上下文

更好的方法可能是在上下文中设置accountId,并在存储库中使用该上下文:

public class ExecutionContext
{
    public Guid AccountId { get; set; } = Guid.NewGuid();
}

存储库长这样:
public class MyRepository
{
    public ExecutionContext Context { get; }

    public MyRepository(ExecutionContext context)
    {
        Context = context;
    }
}

使上下文可注入...
var container = new Container(_ =>
{
    _.Injectable<ExecutionContext>();
});

然后,在您的工厂中...
public MyRepository GetRepositoryForAccount(string accountId) {
    var nested = container.GetNestedContainer();
    var context = new ExecutionContext{ AccountId = accountId };
    nested.Inject(context);
    return nested.GetInstance<IMyRepository>()
}

文档:https://jasperfx.github.io/lamar/documentation/ioc/injecting-at-runtime/

在这种情况下,您可能还需要考虑是否真正需要工厂,或者直接使用嵌套的可注入容器是否可以使设计更清晰。


感谢@adhominem。虽然这个答案展示了解决问题的好方法,但我仍然希望有人能提供一个“像使用StructureMap一样容易”的解决方案。 - Christoph Lütjen

0

粗鲁但简单的解决方案可能是下面的代码:

var type = container.Model.DefaultTypeFor(typeof(IMyRepository));
var constructor = type.GetConstructor(new[] { typeof(string) });
var instance = constructor.Invoke(new object[] { accountId });
return (IMyRepository)instance;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接