【问题标题】:How to tackle behavior variation with StructureMap?如何使用 StructureMap 解决行为变化?
【发布时间】:2012-08-09 00:15:25
【问题描述】:

我有一组注册到 StructureMap 的组件。根据实际租户解决组件的最佳方法应该是什么?

小例子: 有两个租户,比如说,黄色和绿色。 我有一个IValidator,它有两个实现:YellowValidatorGreenValidator。 假设应用程序是 MVC,并且 tentant 来自 URL。 所以,我只需要根据租户注入正确的IValidator

我见过许多只处理多租户数据的多租户应用程序解决方案,通常根据租户配置不同的数据库。这仅涉及参数传递。但这种情况下,变化发生在行为中,而不是在数据中。我希望 IoC 容器透明地解析正确的实例。

编辑:更多信息: IValidator 接口有一个简单的方法bool Validate(),但是实现需要一些注入。

还有其他自定义验证器,但两个租户都使用它们。

有一个基于 URL 的明确的 tentant 策略。这意味着每个请求可以有不同的租户,并且单个应用程序可以为两个租户提供服务。

【问题讨论】:

  • 您能否提供更多背景信息,例如:IValidator 界面实际上是什么样的?验证者当前是如何注册的。 YellowValidatorGreenValidator 是系统中仅有的两个验证器,还是有许多验证器几乎都用于两个租户,而只有几个不同?你如何确定租户是什么?每个 Web 应用程序/应用程序域是否有一个租户(在启动时确定,可能在 XML 中注册)或者您是否同时有多个租户并且每个请求可以有不同的租户。

标签: ioc-container structuremap multi-tenant


【解决方案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);

我希望这会有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-02-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-03
    相关资源
    最近更新 更多