Dans mon bootstrapper:
namespace Conduit.Mam.ClientServices.Common.Initizliaer
{
public static class Initializer
{
private static bool isInitialize;
private static readonly object LockObj = new object();
private static IUnityContainer defaultContainer = new UnityContainer();
static Initializer()
{
Initialize();
}
public static void Initialize()
{
if (isInitialize)
return;
lock (LockObj)
{
IUnityContainer container = defaultContainer;
//registering Unity for MVC
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
//registering Unity for web API
// GlobalConfiguration.Configuration.DependencyResolver = new Unity.WebApi.UnityDependencyResolver(container);
#region managers
container.RegisterType<ISettingsManager, SettingsManager>();
container.RegisterType<IMamDataManager, MamDataManager>();
container.RegisterType<IAppsDataManager, AppsDataManager>();
#endregion
if (!isInitialize)
{
isInitialize = true;
}
}
}
}
}
dans le code de mon contrôleur:
ISettingsManager sm = mUnityContainer.Resolve<ISettingsManager>();
en survolant sur mUnityContainer, je vois que ISettingsManager
est associé à SettingsManager
mais alors j'obtiens l'erreur:
L'exception est la suivante: InvalidOperationException - Le type actuel est un interface et ne peut pas être construit. Il vous manque un mappage de type?
J'ai aussi essayé
ISettingsManager sm = (ISettingsManager)mUnityContainer.Resolve<>(typeof(ISettingsManager));
mais pas d'utilisation
Vous utilisez de manière incorrecte l’Injection de dépendance. La bonne façon de faire est que vos contrôleurs prennent les dépendances dont ils ont besoin et laissent au framework d’injection de dépendance injecter les instances concrètes:
public class HomeController: Controller
{
private readonly ISettingsManager settingsManager;
public HomeController(ISettingsManager settingsManager)
{
this.settingsManager = settingsManager;
}
public ActionResult Index()
{
// you could use the this.settingsManager here
}
}
Comme vous pouvez le voir dans cet exemple, le contrôleur ne sait rien du conteneur. Et c'est comme ça que ça devrait être.
Tout le câblage DI devrait avoir lieu dans votre Bootstraper. Vous ne devriez jamais utiliser d'appels container.Resolve<>
dans votre code.
En ce qui concerne votre erreur, la mUnityContainer
que vous utilisez dans votre contrôleur n’est probablement pas la même instance que celle construite dans votre Bootstraper. Mais comme vous ne devriez utiliser aucun code de conteneur dans vos contrôleurs, cela ne devrait plus être un problème.
Juste pour les autres (comme moi) qui auraient pu faire face à l'erreur ci-dessus. La solution en termes simples.
Vous avez peut-être manqué d'enregistrer votre interface et votre classe (qui implémente cette interface) dans votre code.
par exemple si l'erreur est
"Le type actuel, xyznamespace. Imyinterfacename, est une interface et ne peut pas être construit. Il vous manque un mappage de type? "
Vous devez ensuite enregistrer la classe qui implémente la Imyinterfacename dans la classe UnityConfig dans la méthode Register. en utilisant le code comme ci-dessous
container.RegisterType<Imyinterfacename, myinterfaceimplclassname>();
Dans mon cas, je recevais cette erreur malgré l'enregistrement d'une instance existante pour l'interface en question.
En fait, c’est parce que j’utilisais Unity dans WebForms avec le package Unity.WebForms Nuget et que j’avais spécifié un gestionnaire Hierarchical Lifetime pour la dépendance pour laquelle je fournissais une instance, mais un gestionnaire de durée de vie transitoire pour un type ultérieur dépendant du type précédent - ce n'est généralement pas un problème - mais avec Unity.WebForms, les gestionnaires de durée de vie fonctionnent un peu différemment ... vos types injectés semblent nécessiter un gestionnaire de durée de vie hiérarchique, mais un nouveau conteneur est toujours créé pour chaque requête Web (en raison de l'architecture des formulaires Web, je suppose), comme expliqué de manière excellente dans cet article .
Quoi qu'il en soit, je l'ai résolu en ne spécifiant tout simplement pas de gestionnaire de durée de vie pour les types/instances lors de leur enregistrement.
c'est à dire.
container.RegisterInstance<IMapper>(MappingConfig.GetMapper(), new HierarchicalLifetimeManager());
container.RegisterType<IUserContext, UserContext>(new TransientLifetimeManager());
devient
container.RegisterInstance<IMapper>(MappingConfig.GetMapper());
container.RegisterType<IUserContext, UserContext>();
Pour qu'IMapper puisse être résolu avec succès ici:
public class UserContext : BaseContext, IUserContext
{
public UserContext(IMapper _mapper) : base(_mapper)
{
}
...
}
Le code ci-dessous vous sera utile
public static IUnityContainer Initialise(IUnityContainer container = null)
{
if (container == null)
{
container = new UnityContainer();
}
container.RegisterType<ISettingsManager, SettingsManager>();
container.Resolve<SettingsManager>();
container.RegisterType<SettingsManagerController>(new InjectionProperty("_SettingManagerProvider", new ResolvedParameter<ISettingManager>()));
return container;
}
J'ai eu ce problème et la cause était que je n'avais pas ajouté le package Microsoft.Owin.Host.SystemWeb NuGet à mon projet. Bien que le code de ma classe de démarrage soit correct, il n'était pas exécuté.
Donc, si vous essayez de résoudre ce problème, insérez un point d'arrêt dans le code où vous effectuez les enregistrements Unity. Si vous ne le faites pas, votre injection de dépendance ne fonctionnera pas.
Dans mon cas, j’ai utilisé 2 contextes différents avec Unitofwork et le conteneur Ioc, ce qui me pose problème alors que la couche service essaie de faire injecter un deuxième référentiel à DI. La raison en est que le module exist contient une autre instance de module et un conteneur censés recevoir un appel d'un nouveau référentiel non construit. Je vous écris ici pour savoir ce qui se passe dans mes shooes
Vous n’enregistrez peut-être pas les contrôleurs ..__ Essayez le code ci-dessous:
Étape 1 . Écrivez votre propre classe d'usine de contrôleur ControllerFactory: DefaultControllerFactory en implémentant le dossier defaultcontrollerfactoryin
public class ControllerFactory :DefaultControllerFactory
{
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
try
{
if (controllerType == null)
throw new ArgumentNullException("controllerType");
if (!typeof(IController).IsAssignableFrom(controllerType))
throw new ArgumentException(string.Format(
"Type requested is not a controller: {0}",
controllerType.Name),
"controllerType");
return MvcUnityContainer.Container.Resolve(controllerType) as IController;
}
catch
{
return null;
}
}
public static class MvcUnityContainer
{
public static UnityContainer Container { get; set; }
}
}
Étape 2: Enregistrez-le dans BootStrap: méthode InBuildUnityContainer
private static IUnityContainer BuildUnityContainer()
{
var container = new UnityContainer();
// register all your components with the container here
// it is NOT necessary to register your controllers
// e.g. container.RegisterType<ITestService, TestService>();
//RegisterTypes(container);
container = new UnityContainer();
container.RegisterType<IProductRepository, ProductRepository>();
MvcUnityContainer.Container = container;
return container;
}
Étape 3: Dans Global Asax.
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
AuthConfig.RegisterAuth();
Bootstrapper.Initialise();
ControllerBuilder.Current.SetControllerFactory(typeof(ControllerFactory));
}
Et vous avez terminé