2017-07-05 3 views
1

J'ai un projet ASP.Net MVC 5 utilisant une architecture Onion où j'ai des dépôts et des services et j'utilise les services de mon contrôleur. Dans mon contrôleur, j'ai besoin d'utiliser les variables IGenericService que j'ai créées, mais comment puis-je instancier ces variables? Le problème étant que mon service a besoin d'un IRepository pour son constructeur, et à son tour IRepository doit être initialisé aussi.Comment instancier des services dans MVC

Ce que j'ai essayé était AddSingleton(IGenericService<MyClass>, GenericService<MyClass>) dans la méthode ConfigureServices(IServiceCollection services) dans le fichier Startup.cs mais cela ne semble pas aider.

Modifier Comme suggéré mon @Nkosi j'essaye de résoudre des dépendances et a suivi ce tutoriel pour faire ainsi: http://scottdorman.github.io/2016/03/17/integrating-asp.net-core-dependency-injection-in-mvc-4/. Mon problème est maintenant que je reçois un invalid operation exception:

Impossible de résoudre le service de type « Repository.PrincipalServerContext » tout en essayant d'activer « WebExploitv2.Controllers.NavigationController »

Mon startup.cs ressemble maintenant:

public partial class Startup 
{ 
    public void Configuration(IAppBuilder app) 
    { 
     var services = new ServiceCollection(); 
     ConfigureAuth(app); 
     ConfigureServices(services); 
     var resolver = new DefaultDependencyResolver(services.BuildServiceProvider()); 
     DependencyResolver.SetResolver(resolver); 
    } 

    public void ConfigureServices(IServiceCollection services) 
    { 
     services.AddControllerAsServices(typeof(Startup).Assembly.GetExportedTypes() 
      .Where(t => !t.IsAbstract && !t.IsGenericTypeDefinition) 
      .Where(t => typeof(IController).IsAssignableFrom(t) 
       || t.Name.EndsWith("Controller", StringComparison.OrdinalIgnoreCase))); 

     services.AddSingleton<IGenericRepository<Web_Documents>, GenericRepository<Web_Documents>>(); 
     services.AddSingleton<IGenericService<Web_Documents>, GenericService<Web_Documents>>(); 

     services.AddSingleton<IGenericRepository<Web_Categories>, GenericRepository<Web_Categories>>(); 
     services.AddSingleton<IGenericService<Web_Categories>, GenericService<Web_Categories>>(); 

     services.AddSingleton<IGenericService<Web_User_joint_Profils>, GenericService<Web_User_joint_Profils>>(); 
     services.AddSingleton<IGenericRepository<Web_User_joint_Profils>, GenericRepository<Web_User_joint_Profils>>(); 

     services.AddSingleton<IGenericRepository<Web_Group_joint_Profils>, GenericRepository<Web_Group_joint_Profils>>(); 
     services.AddSingleton<IGenericService<Web_Group_joint_Profils>, GenericService<Web_Group_joint_Profils>>(); 


     services.AddSingleton<IMenuService, MenuService>(); 
     services.AddSingleton<IMenuRepository, MenuRepository>(); 
    } 
} 

J'ai aussi ajouté une classe DefaultDependencyResolver:

public class DefaultDependencyResolver : IDependencyResolver 
{ 
    protected IServiceProvider serviceProvider; 

    public DefaultDependencyResolver(IServiceProvider serviceProvider) 
    { 
     this.serviceProvider = serviceProvider; 
    } 

    public object GetService(Type serviceType) 
    { 
     return this.serviceProvider.GetService(serviceType); 
    } 

    public IEnumerable<object> GetServices(Type serviceType) 
    { 
     return this.serviceProvider.GetServices(serviceType); 
    } 
} 

Ensuite, j'ai la classe ServiceProviderExtension:

public static class ServiceProviderExtensions 
{ 
    public static IServiceCollection AddControllerAsServices(this IServiceCollection services, IEnumerable<Type> controllerTypes) 
    { 
     foreach(var type in controllerTypes) 
     { 
      services.AddTransient(type); 
     } 
     return services; 
    } 
} 

Enfin, dans mon contrôleur, j'ai Interfaces de GenericService qui me permet d'accéder Repository et l'accès à mon tour DB. J'utilise les interfaces suivre pour instanciation

private IGenericService<Web_User_joint_Profils> _userProfileService; 
    private IGenericService<Web_Group_joint_Profils> _groupProfileService; 
    private IGenericService<Web_Categories> _categoryService; 
    PrincipalServerContext context; 
    private NavigationController(PrincipalServerContext context, IGenericService<Web_User_joint_Profils> userProfileService, IGenericService<Web_Group_joint_Profils> groupProfileService, IGenericService<Web_Categories> categoryService) 
    { 
     _context = context; 
     _userProfileService = userProfileService; 
     _groupProfileService = groupProfileService; 
     _categoryService = categoryService; 
    } 

Notez que mon GenericService prend Poços comme génériques afin de savoir où chercher dans la base de données. Donc pour chacun d'entre eux dans Startup.ConfigureServices(IServiceCollection services) j'ai ajouté une méthode AddSingleton pour enregistrer ces services et dépôts avec le conteneur DI. Des idées pour lesquelles je reçois cette exception?

+0

Vous devez vous enregistrer toutes les dépendances dans le graphe d'objets – Nkosi

+1

Documentation ici - https://docs.microsoft.com/en-us/aspnet/ core/fundamentals/dependency-injection – Nkosi

+0

Est-il normal que je ne puisse pas utiliser la méthode 'AddDbContext ()'? Beaucoup d'autres fonctionnent bien, mais je ne peux pas pour celui-ci, ou même 'AddMvc()' –

Répondre

1

Il est assez simple, en utilisant par exemple IServiceCollection qui est passé à ConfigureServices méthode par le temps d'exécution vous:

services.AddSingleton<IAbstraction, ConcreteImplementation>(); 

ou, pour une portée de vie transitoire:

services.AddTransient<IAbstraction, ConcreteImplementation>(); 

ou, dans votre cas:

services.AddSingleton<IGenericService<MyClass>, GenericService<MyClass>>(); 
+0

Cela ne marche pas Je ne sais pas pourquoi, c'est la solution que je trouverais mais je reçois toujours une exception de référence Null –

+0

@ LéonardLaiter comment vous essayez d'injecter les dépendances? – Alex

+0

Je crois que c'est l'étape que j'ai ignorée: p Lire le document que @Nkosi a posté et je vous le dirai quand j'y serai. –

1

Je n'appellerais pas les services à l'intérieur d'une st artup.

Installez votre IGenericService en lecture seule, puis créez le constructeur pour appeler startup.cs ou vous décidez de l'utiliser.

private readonly IGenericService _genericService = new GenericService(); 
public IGenericService GenericService 
{ 
    get{ return _genericService; } 
    set{ _genericService = value; } 
} 

Maintenant que vous appelez vos cours comme:

GenericService.Method();