我有一组注册到StructureMap的组件。根据实际租户解决组件的最佳方法是什么?
小例子:
有两个租户,比如黄色和绿色。
我有一个IValidator
,它有两个实现:YellowValidator
和GreenValidator
。
假设应用程序是MVC并且帐篷来自URL。
所以,我只需要根据租户注入适当的IValidator
。
我见过很多针对多租户应用程序的解决方案,它们只处理多租户数据,根据租户规范配置不同的数据库。这只涉及参数传递。但这种情况是行为发生变化,而不是数据。我希望IoC容器透明地解析正确的实例。
编辑:更多信息:
IValidator接口有一个简单的方法bool Validate()
,但实现需要一些注入。
还有其他自定义验证器,但两个租户都使用它们。
基于URL有一个明确的帐篷策略。这意味着每个请求可以拥有不同的租户,并且单个应用程序可以为两个租户提供服务。
答案 0 :(得分:1)
有许多方法可以给猫皮肤。我很难猜测你的应用程序的设计,所以这是一个想法。要记住的事情是隐藏composite后面的验证器,以允许IValidator
接口的用户对许多实现一无所知。这样的复合材料看起来像这样:
public class ValidatorComposite : IValidator
{
private IEnumerable<IValidator> validators;
public ValidatorComposite(
IEnumerable<IValidator> validators)
{
this.validators = validators;
}
public bool Validate(object instance)
{
return this.validators.All(v => v.Validate(instance));
}
}
您可以创建多个复合并按键注册,其中键是租户的名称(但没有键控注册可能同样容易)。这些复合材料可以包装在另一个复合材料中,该复合材料将委托给适当的特定租户复合材料。这样的租户选择合成可能如下所示:
public class TenantValidatorComposite : IValidator
{
private ITenantContext tenantContext;
private IValidator defaultValidator;
private IDictionary<string, IValidator> tenantValidators;
public ValidatorComposite(
ITenantContext tenantContext,
IValidator defaultValidator,
IDictionary<string, IValidator> tenantValidators)
{
this.tenantContext = tenantContext;
this.defaultValidator = defaultValidator;
this.tenantValidators = tenantValidators;
}
public bool Validate(object instance)
{
string name = this.tenantContext.CurrentTenant.Name;
return this.defaultValidator.Validate(instance) &&
this.tenantValidators[name].Validate(instance);
}
}
ITenantContext
是一种抽象,允许您在当前上下文中获取当前租户。你可能已经有类似的东西,但我想一个实现看起来像这样:
class UrlBasedTenantContext : ITenantContext
{
public Tenant Current
{
get
{
// Naive implementation.
if (HttpContext.Current.Request.Url.Contains("tenant1"))
{
return Tenant1;
}
return Tenant2;
}
}
}
创建TenantValidatorComposite
很简单:
var defaultValidator = CompositeValidator(
GetAllDefaultValidators());
var tenantValidators = new Dictionary<string, IValidator>()
{
{ "tenant1", new CompositeValidator(GetValidatorsFor("tenant1")) },
{ "tenant2", new CompositeValidator(GetValidatorsFor("tenant2")) },
};
var tenantValidator = new TenantValidatorComposite(
new UrlBasedTenantContext(),
defaultValidator,
tenantValidators);
我希望这会有所帮助。