C# 每个“组织"的不同实例/SaaS 的自定义代码 [英] C# Different instance per "organization" / custom code for SaaS

查看:21
本文介绍了C# 每个“组织"的不同实例/SaaS 的自定义代码的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am writing a (C# ASP.NET API) program that is intended to be used as a SaaS. The program has standard features but the old (non-SaaS) also had per customer some custom code for connecting with their system. Resulting in a different version of the code per customer.

我对此的一个解决方案是使用松散耦合.但是我如何才能在运行时调用接口的不同实例?最好没有 switch-case/if-tree.

One solution I have for this would be to use Loose coupling. But how could I make it so that a different instance of the interface is called on runtime? And preferably without a switch-case / if-tree.

对此解决方案的任何帮助都会很好,但我也想知道这是否可行?

Any help on this solution would be nice, but I also wonder if this is the way to go?

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

In other programming languages e.g. javascript you can load and run code JIT. Another connected solution would be to use a microservice for the parts where it needs to connect to the customer's system. By doing this I could update the connector independently from the main program.

推荐答案

您可以在依赖注入容器中连接实现并在运行时选择实现.

You could wire up the implementations in the dependency injection container and pick the implementation at runtime.

假设您有一个 IDiscountCalculator 接口,根据客户要求有几个不同的实现.

Assume you have a IDiscountCalculator interface, with a couple of different implementations per customer requirements.

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

You'd get the current tenant/customer info from the request and decide which implementation needs to be run, then return the appropriate implementation.

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

Take this example (I'm keeping the level of abstraction to minimum)

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 以进行良好测量:

You'd probably abstract this to a factory DiscountCalculatorFactory for good measure:

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;
}

这篇关于C# 每个“组织"的不同实例/SaaS 的自定义代码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆