J'utilise Autofac comme système d'injection de dépendances dans une solution C# qui englobe plusieurs bibliothèques de classes et plusieurs exécutables. J'utilise des modules pour configurer Autofac, mais cela me laisse toujours le problème de la construction du conteneur DI, qui varie selon l'exécutable pour lequel je le compose.
J'ai essayé d'utiliser RegisterAssemblyModules d'Autofac, mais vous devez lui donner une liste d'assemblages à analyser, et jusqu'à ce qu'un certain type d'assemblage dans une bibliothèque de classe soit utilisé, l'assemblage n'est pas chargé, et donc pas disponible pour l'analyse.
Certaines personnes recommandent de charger chaque assemblage du répertoire bin qui pourrait contenir une définition de module Autofac. Mais cela semble poser le risque qu'un assemblage non désiré se glisse dans l'action.
J'ai donc créé cette classe statique, qui est définie dans une bibliothèque de classes communes :
public static class Container
{
private static IContainer _instance;
private static Dictionary<string, Assembly> _moduleAssemblies = new Dictionary<string, Assembly>();
public static void RegisterAutofacModuleAssembly<T>()
where T : class
{
var assembly = typeof(T).Assembly;
if( !_moduleAssemblies.ContainsKey( assembly.FullName ) )
_moduleAssemblies.Add( assembly.FullName, assembly );
}
public static IContainer Instance
{
get
{
if( _instance == null )
{
var builder = new ContainerBuilder();
builder.RegisterAssemblyModules( _moduleAssemblies.Select( ma => ma.Value ).ToArray() );
_instance = builder.Build();
}
return _instance;
}
}
}
Vous l'utilisez en incluant des lignes comme celle-ci dans le code de démarrage d'une application :
public static void Main(string[] args)
{
AutoFacRegistrar.Container.RegisterAutofacModuleAssembly<ScannerApp>();
AutoFacRegistrar.Container.RegisterAutofacModuleAssembly<AppConfiguration>();
S'agit-il d'une solution raisonnable ? S'il en existe une meilleure, plus souple, j'aimerais la connaître.
Question en IOptions<>
Système de fixation
En mettant en œuvre la suggestion de @Nightowl888, j'ai rencontré un problème avec la configuration Microsoft IOptions<>
système. Voici comment j'essaie de configurer Autofac pour résoudre les objets AppConfiguration :
protected override void Load( ContainerBuilder builder )
{
base.Load( builder );
var config = new ConfigurationBuilder()
.AddJsonFile( AppConfiguration.WebJobsConfigFile, false )
.AddUserSecrets<ConfigurationModule>()
.AddEnvironmentVariables()
.Build();
builder.Register<AppConfiguration>( ( c, p ) =>
{
var retVal = new AppConfiguration( c.Resolve<ILogger>() );
config.Bind( retVal );
return retVal;
} )
.SingleInstance();
}
Le problème se produit dans l'appel à Bind(). En parcourant et en analysant les informations de configuration, il s'attend à créer divers objets par le biais de constructeurs sans paramètres... ce qui rend difficile l'utilisation de l'injection des constructeurs.
Si je ne peux pas utiliser l'injection de constructeur, je dois être capable de résoudre contre le conteneur DI dans le code du constructeur. Je ne vois pas comment je peux définir un assemblage de bibliothèque qui n'intègre pas la sémantique de résolution d'un conteneur DI particulier.
Réflexions ? Autre que "abandonner le IOptions<>
système", que j'ai envisagé, mais il offre un certain nombre d'avantages que j'aimerais conserver.