6

Autofac 3.0 avrà un supporto MultitenantIntegration e its preview release is out ora. Per provarlo, ho creato un'applicazione API Web ASP.NET con la seguente configurazione:Contenitore IoC multi-tenant di Autofac in un'applicazione API Web ASP.NET

public class Global : System.Web.HttpApplication { 

    protected void Application_Start(object sender, EventArgs e) { 

     var config = GlobalConfiguration.Configuration; 
     config.Routes.MapHttpRoute("Default", "api/{controller}"); 
     RegisterDependencies(config); 
    } 

    public void RegisterDependencies(HttpConfiguration config) { 

     var builder = new ContainerBuilder(); 
     builder.RegisterApiControllers(Assembly.GetExecutingAssembly()); 

     // creates a logger instance per tenant 
     builder.RegisterType<LoggerService>().As<ILoggerService>().InstancePerTenant(); 

     var mtc = new MultitenantContainer(
      new RequestParameterTenantIdentificationStrategy("tenant"), 
      builder.Build()); 

     config.DependencyResolver = new AutofacWebApiDependencyResolver(mtc); 
    } 
} 

ottiene il lavoro fatto e crea un'istanza LoggerService come ILoggerService per abbonato. Ho due problemi in questa fase, che non ero in grado di risolvere:

  1. ho usato fuori dalla scatola fornito RequestParameterTenantIdentificationStrategy qui come il TenantIdentificationStrategy solo per questa applicazione demo. Sono in grado di creare la mia personalizzata TenantIdentificationStrategy implementando l'interfaccia ITenantIdentificationStrategy. Tuttavia, il metodo TryIdentifyTenant di ITenantIdentificationStrategy fa affidamento su un'istanza statica come HttpContext.Current che è qualcosa che non desidero in un ambiente API Web ASP.NET poiché desidero che la mia API stia ospitando l'agnostico (so che posso delegare questo lavoro al livello di hosting, ma preferirei non farlo). C'è un altro modo per raggiungere questo in un modo che non farò affidamento su un'istanza statica?
  2. mi hanno anche la possibilità di registrare un'istanza specifica inquilino come di seguito:

    mtc.ConfigureTenant("tenant1", cb => cb.RegisterType<Foo>() 
                .As<IFoo>().InstancePerApiRequest()); 
    

    Tuttavia, uno dei miei situazioni mi obbliga a passare il nome dell'inquilino attraverso il parametro del costruttore e mi piacerebbe avere qualcosa di simile qui sotto :

    mtc.ConfigureTenant((cb, tenantName) => cb.RegisterType<Foo>() 
                .As<IFoo>() 
                .WithParameter("tenantName", tenantName) 
                .InstancePerApiRequest()); 
    

    Attualmente non esiste una tale API. C'è un altro modo per raggiungere questo o questo tipo di requisito non ha senso?

risposta

4

supporto Multitenant è stato disponibile per un lungo periodo di tempo, è solo che 3.0 è la prima volta che abbiamo avuto un pacchetto NuGet per esso. :)

Il RequestParameterTenantIdentificationStrategy è, come documentato, solo un esempio molto semplice che mostra un modo possibile (e non consigliato) per identificare il titolare. Dovrai scegliere autonomamente come identificare il tuo inquilino in base al contesto operativo. Potrebbe essere un valore web.config, una variabile di ambiente o qualche altra cosa nell'ambiente corrente. Se non si desidera utilizzare HttpContext.Current, non farlo. Spetta a te scegliere da dove ricevi le informazioni.

(Una nota sul RPTIStrategy -. La parte che non è raccomandato sta utilizzando un parametro querystring o richiesta come il meccanismo inquilino ID utilizzare HttpContext nelle mie applicazioni di produzione e funziona benissimo C'è solo così tanto si può astratto. prima che sia necessario toccare il metallo nudo.)

Non esiste alcun modo per fornire la sintassi di registrazione lambda richiesta, principalmente perché l'inquilino non è passato attraverso il processo di risoluzione. Il processo di risoluzione è:

  1. Identificare l'inquilino con la strategia.
  2. Trova l'ambito di durata della vita configurato del titolare.
  3. Utilizzare la sintassi di stile Autofac Resolve standard.

È intenzionalmente semplice e analogo alle operazioni esistenti.Al momento della risoluzione, il sub-lifetime-scope appartenente al tenant è taggato con l'ID tenant ma l'operazione di risoluzione non conosce l'ID tenant ... quindi il lambda non funzionerebbe (e probabilmente vinto In qualunque momento presto perché cambierebbe gli interni fondamentali del modo in cui funziona Autofac se lo facesse).

per compiere ciò che stai cercando, è possibile utilizzare una combinazione di estensione InstancePerTenant al momento della registrazione ...

var builder = new ContainerBuilder(); 
builder.RegisterType<Foo>().As<IFoo>().InstancePerTenant(); 

... e la registrazione del ITenantIdentificationStrategy come una dipendenza nel vostro contenitore.

builder.Register(myIdStrategy).As<ITenantIdentificationStrategy>(); 

poi prendere la vostra classe di prendere un ITenantIdentificationStrategy piuttosto che l'ID del locatario direttamente. Utilizzare la strategia per ottenere l'ID titolare invece.

Se si vuole davvero essere fantasiosi, è possibile registrare un lambda con chiave che risolve la strategia ID, quindi ottiene l'ID titolare. Quindi potresti aggiungere una registrazione dei parametri all'oggetto come hai fatto ma utilizzando un servizio con chiave. (Ho intenzione di andare a memoria, in modo che dovrete controllare due volte la mia sintassi qui, ma sarà qualcosa di simile ...)

builder.Register(c => 
     { var s = c.Resolve<ITenantIdentificationStrategy>(); 
      object id; 
      s.TryIdentifyTenant(out id); 
      return id; 
     }).Keyed<object>("tenantId"); 

builder.RegisterType<Foo>() 
     .As<IFoo>() 
     .WithParameter(
     (pi, c) => pi.Name == "tenantId", 
     (pi, c) => c.ResolveKeyed<object>("tenantId")) 
     .InstancePerApiRequest(); 

Anche in questo caso, ti consigliamo di ricontrollimi, ma sono abbastanza sicuro che (o una variazione minore) dovrebbe funzionare per ottenere ciò che desideri.

+0

Grazie Travis. Davvero utile Il tuo ultimo campione è davvero quello che sto cercando. Avrei dovuto pensarci prima :) Quindi, il mio 'ITenantIdentificationStrategy' ha davvero bisogno di un oggetto statico. Quindi non c'è altra opzione per me piuttosto che delegare 'TenantIdentificationStrategy' al livello di hosting che ha il contesto statico per richiesta. – tugberk