首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >针对SaaS的每个“组织”/自定义代码C#不同的实例

针对SaaS的每个“组织”/自定义代码C#不同的实例
EN

Stack Overflow用户
提问于 2021-07-29 20:56:33
回答 1查看 55关注 0票数 0

我正在写一个(C# ASP.NET API)程序,打算用作SaaS。该程序具有标准功能,但旧的(非SaaS)也为每个客户提供了一些用于连接其系统的自定义代码。导致每个客户的代码版本不同。

我对此的一个解决方案是使用松散耦合。但是,我如何才能使接口的另一个实例在运行时被调用?并且优选地没有开关盒/if树。

任何关于这个解决方案的帮助都会很好,但我也想知道这是不是可行的方法?

在其他编程语言中,例如javascript,您可以加载和运行代码JIT。另一种连接的解决方案是对需要连接到客户系统的部件使用微服务。通过这样做,我可以独立于主程序更新连接器。

EN

回答 1

Stack Overflow用户

发布于 2021-07-29 13:14:10

您可以将依赖项注入容器中的实现连接起来,并在运行时挑选实现。

假设您有一个IDiscountCalculator接口,每个客户需求有几个不同的实现。

您将从请求中获得当前的租户/客户信息,并决定需要运行哪个实现,然后返回适当的实现。

以这个例子为例(我将抽象级别保持在最低限度)

代码语言:javascript
复制
services.AddScoped<IDiscountCalculator>(provider =>
{
    // find the tenant
    var user = provider.GetRequiredService<IHttpContextAccessor>().HttpContext!.User;
    var tenantId = user.FindFirstValue("tenant_id");
    var tenant = provider.GetRequiredService<AppDbContext>().Tenants.Single(t => t.Id == tenantId);
    
    // return the implementation based on tenant's preferences
    return tenant.DiscountType switch
    {
        typeof(SpecialDiscountCalculator).Name => provider.GetRequiredService<SpecialDiscountCalculator>(),
        // ... other implementations

        // default to standard discount
        _ => provider.GetRequiredService<StandardDiscountCalculator>();
    };
});

为了更好地衡量,您可能会将其抽象为工厂DiscountCalculatorFactory

代码语言:javascript
复制
class DiscountCalculatorFactory
{
    private IPrincipalAccessor _principalAccessor;
    private AppDbContext _dbContext;

    public DiscountCalculatorFactory(AppDbContext dbContext, IPrincipalAccessor principalAccessor)
    {
        _dbContext = dbContext;
        _principalAccessor = principalAccessor;
    }

    public async Task<IDiscountCalculator> CreateAsync()
    {
        var user = _principalAccessor.Principal;
        var tenantId = user.FindFirstValue("tenant_id");
        var tenant = await _dbContext.Tenants.SingleAsync(t => t.Id == tenantId);
        
        return tenant.DiscountType switch
        {
            typeof(SpecialDiscountCalculator).FullName => provider.GetRequiredService<SpecialDiscountCalculator>(),
            // ... other implementations

            // default
            _ => provider.GetRequiredService<DefaultDiscountCalculator>();
        };
    }
}

public interface IPrincipalAccessor {
    ClaimsPrincipal? Principal { get; }
}

public class HttpPrincipalAccessor : IPrincipalAccessor
{
    private IHttpContextAccessor _httpContextAccessor;

    public HttpPrincipalAccessor(IHttpContextAccessor httpContextAccessor)
    {
        _httpContextAccessor = httpContextAccessor;
    }

    public ClaimsPrincipal? Principal => _httpContextAccessor?.HttpContext?.User;
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68576342

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档