0

StructureMap に登録された一連のコンポーネントがあります。実際のテナントに応じて、コンポーネントを解決する最善の方法は何ですか?

小さな例: たとえば、Yellow と Green という 2 つのテナントがあります。IValidatorと の2 つの実装を持つ がありYellowValidatorますGreenValidator。アプリケーションが MVC であり、テントが URL から来るとします。したがって、IValidatorテナントに応じて適切に注入する必要があります。

私は、データのマルチテナンシーのみを扱うマルチテナント アプリケーションの多くのソリューションを見てきました。通常は、テナントに応じて異なるデータベースを構成します。これには、パラメーターの受け渡しのみが含まれます。しかし、これは変動がデータではなく行動に発生する場合です。IoC コンテナーが適切なインスタンスを透過的に解決するようにします。

編集: 詳細: IValidator インターフェイスには単純なメソッドbool Validate()がありますが、実装にはいくつかの注入が必要です。

他にもカスタム バリデーターがありますが、両方のテナントで使用されています。

URL に基づく明確なテント戦略があります。これは、各要求が異なるテナントを持つことができ、単一のアプリケーションが両方のテナントにサービスを提供することを意味します。

4

1 に答える 1

1

猫の皮を剥ぐ方法はたくさんあります。あなたのアプリケーションのデザインを推測するのは難しいので、ここにアイデアがあります。念頭に置いていることは、バリデーターを複合体の背後に隠して、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);

これが役立つことを願っています。

于 2012-08-15T19:28:00.417 に答える