programing

ASP.NET MVC 5에 대한 종속성 주입을 만드는 방법은 무엇입니까?

linuxpc 2023. 6. 30. 22:09
반응형

ASP.NET MVC 5에 대한 종속성 주입을 만드는 방법은 무엇입니까?

ASP.NET Core를 사용하여 종속성 주입을 만드는 것은 매우 쉽습니다.이 문서는 여기에 그것을 아주 잘 설명하고 있고 이 남자는 그것을 설명할 킬러 비디오를 가지고 있습니다.

그러나 ASP.NET MVC 5 프로젝트에서도 동일한 작업을 수행하고 싶습니다.ASP.MVC 5로 종속성 주입을 처리하는 방법은 무엇입니까?

또한 종속성 주입은 컨트롤러로만 제한됩니까? 아니면 모든 클래스에서 작동할 수 있습니까?

ASP.Net MVC에서 를 사용할 수 있습니다.타사 대안 중 하나가 아닌 NuGet의 NetCore DI:

using Microsoft.Extensions.DependencyInjection

MVC 시작/구성 클래스의 경우: -

public void Configuration(IAppBuilder app)
{
    // We will use Dependency Injection for all controllers and other classes, so we'll need a service collection
    var services = new ServiceCollection();

    // configure all of the services required for DI
    ConfigureServices(services);

    // Configure authentication
    ConfigureAuth(app);

    // Create a new resolver from our own default implementation
    var resolver = new DefaultDependencyResolver(services.BuildServiceProvider());

    // Set the application resolver to our default resolver. This comes from "System.Web.Mvc"
    //Other services may be added elsewhere through time
    DependencyResolver.SetResolver(resolver);
}

제 프로젝트는 Identity User를 사용하며 OWIN 시작 구성을 대신하여 서비스 기반 접근 방식을 따르도록 변경했습니다.기본 ID 사용자 클래스는 정적 팩토리 메서드를 사용하여 인스턴스를 생성합니다.저는 그 코드를 생성자로 옮기고 적절한 주입을 제공하기 위해 DI에 의존했습니다.아직 작업 중이지만 제가 있는 곳은 다음과 같습니다.

public void ConfigureServices(IServiceCollection services)
{               
    //====================================================
    // Create the DB context for the IDENTITY database
    //====================================================
    // Add a database context - this can be instantiated with no parameters
    services.AddTransient(typeof(ApplicationDbContext));

    //====================================================
    // ApplicationUserManager
    //====================================================
    // instantiation requires the following instance of the Identity database
    services.AddTransient(typeof(IUserStore<ApplicationUser>), p => new UserStore<ApplicationUser>(new ApplicationDbContext()));

    // with the above defined, we can add the user manager class as a type
    services.AddTransient(typeof(ApplicationUserManager));

    //====================================================
    // ApplicationSignInManager
    //====================================================
    // instantiation requires two parameters, [ApplicationUserManager] (defined above) and [IAuthenticationManager]
    services.AddTransient(typeof(Microsoft.Owin.Security.IAuthenticationManager), p => new OwinContext().Authentication);
    services.AddTransient(typeof(ApplicationSignInManager));

    //====================================================
    // ApplicationRoleManager
    //====================================================
    // Maps the rolemanager of identity role to the concrete role manager type
    services.AddTransient<RoleManager<IdentityRole>, ApplicationRoleManager>();

    // Maps the role store role to the implemented type
    services.AddTransient<IRoleStore<IdentityRole, string>, RoleStore<IdentityRole>>();
    services.AddTransient(typeof(ApplicationRoleManager));
    
    //====================================================
    // Add all controllers as services
    //====================================================
    services.AddControllersAsServices(typeof(Startup).Assembly.GetExportedTypes()
        .Where(t => !t.IsAbstract && !t.IsGenericTypeDefinition)
    .Where(t => typeof(IController).IsAssignableFrom(t)
    || t.Name.EndsWith("Controller", StringComparison.OrdinalIgnoreCase)));
}

계정 컨트롤러 클래스에는 단일 생성자가 있습니다.

[Authorize]
public class AccountController : Controller
{
    private ApplicationSignInManager _signInManager;
    private ApplicationUserManager _userManager;
    private RoleManager<IdentityRole> _roleManager;

    public AccountController(ApplicationUserManager userManager, ApplicationSignInManager signInManager, RoleManager<IdentityRole> roleManager)
    {
        UserManager = userManager;
        SignInManager = signInManager;
        RoleManager = roleManager;
    }
}

내 기본 종속성 확인자:

/// <summary>
/// Provides the default dependency resolver for the application - based on IDependencyResolver, which hhas just two methods
/// </summary>
public class DefaultDependencyResolver : IDependencyResolver
{
    /// <summary>
    /// Provides the service that holds the services
    /// </summary>
    protected IServiceProvider serviceProvider;

    /// <summary>
    /// Create the service resolver using the service provided (Direct Injection pattern)
    /// </summary>
    /// <param name="serviceProvider"></param>
    public DefaultDependencyResolver(IServiceProvider serviceProvider)
    {
        this.serviceProvider = serviceProvider;
    }

    /// <summary>
    /// Get a service by type - assume you get the first one encountered
    /// </summary>
    /// <param name="serviceType"></param>
    /// <returns></returns>
    public object GetService(Type serviceType)
    {
        return this.serviceProvider.GetService(serviceType);
    }

    /// <summary>
    /// Get all services of a type
    /// </summary>
    /// <param name="serviceType"></param>
    /// <returns></returns>
    public IEnumerable<object> GetServices(Type serviceType)
    {
        return this.serviceProvider.GetServices(serviceType);
    }
}

이 답변을 위해 Microsoft Example of WebApi 프로젝트를 예제의 기초로 다운로드하여 아래와 같이 DI 서비스를 추가하였습니다.

  • 대상 프레임워크를 4.6.1로 업데이트
  • NuGet the DI 패키지 :- Microsoft.내선 번호.의존주사

표준 MapHttpRoute 구성 후 필요한 서비스를 등록할 코드를 추가합니다.

의 사용

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Http;
using Microsoft.Extensions.DependencyInjection;
using System.Web.Http.Dependencies;
using ProductsApp.Controllers;

WebApiConfig

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        // Web API routes
        config.MapHttpAttributeRoutes();

        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );

        // create the DI services and make the default resolver
        var services = new ServiceCollection();
        services.AddTransient(typeof(DefaultProduct));
        services.AddTransient(typeof(ProductsController));

        var resolver = new MyDependencyResolver(services.BuildServiceProvider());
        config.DependencyResolver = resolver;
    }
}

기본 제품

public class DefaultProduct : ProductsApp.Models.Product
{
    public DefaultProduct()
    {
        this.Category = "Computing";
        this.Id = 999;
        this.Name = "Direct Injection";
        this.Price = 99.99M;
    }
}

내 종속성 해결기

/// <summary>
/// Provides the default dependency resolver for the application - based on IDependencyResolver, which hhas just two methods.
/// This is combined dependency resolver for MVC and WebAPI usage.
/// </summary>
public class MyDependencyResolver : System.Web.Mvc.IDependencyResolver, System.Web.Http.Dependencies.IDependencyResolver 
{
    protected IServiceProvider serviceProvider;
    protected IServiceScope scope = null;

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

    public MyDependencyResolver(IServiceScope scope) 
    {
        this.scope = scope;
        this.serviceProvider = scope.ServiceProvider;
    }

    public IDependencyScope BeginScope() 
    {
        return new MyDependencyResolver(serviceProvider.CreateScope());
    }

    public void Dispose() 
    {
        Dispose(true);
    }

    protected virtual void Dispose(bool disposing) 
    {
        scope?.Dispose();
    }

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

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

서비스 공급자확장 기능

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

        return services;
    }
}

그런 다음 DI 유형을 사용하도록 기존 컨트롤러를 수정했습니다(CTOR는 하나뿐임).

using ProductsApp.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;

namespace ProductsApp.Controllers
{
    public class ProductsController : ApiController
    {
        DefaultProduct _dp = null;

        public ProductsController(DefaultProduct dp)
        {
            _dp = dp;
            //
            products.Add(dp);
        }

        List<Product> products = new List<Product>()
        {
            new Product { Id = 1, Name = "Tomato Soup", Category = "Groceries", Price = 1 },
            new Product { Id = 2, Name = "Yo-yo", Category = "Toys", Price = 3.75M },
            new Product { Id = 3, Name = "Hammer", Category = "Hardware", Price = 16.99M }
        };

        public IEnumerable<Product> GetAllProducts()
        {
            return products;
        }

        public IHttpActionResult GetProduct(int id)
        {
            var product = products.FirstOrDefault((p) => p.Id == id);
            if (product == null)
            {
                return NotFound();
            }
            return Ok(product);
        }
    }
}

내 기본 종속성 확인자

/// <summary>
/// Provides the default dependency resolver for the application - based on IDependencyResolver, which hhas just two methods
/// </summary>
public class DefaultDependencyResolver : IDependencyResolver
{
    /// <summary>
    /// Provides the service that holds the services
    /// </summary>
    protected IServiceProvider serviceProvider;

    /// <summary>
    /// Create the service resolver using the service provided (Direct Injection pattern)
    /// </summary>
    /// <param name="serviceProvider"></param>
    public DefaultDependencyResolver(IServiceProvider serviceProvider)
    {
        this.serviceProvider = serviceProvider;
    }

    /// <summary>
    /// Get a service by type - assume you get the first one encountered
    /// </summary>
    /// <param name="serviceType"></param>
    /// <returns></returns>
    public object GetService(Type serviceType)
    {
        return this.serviceProvider.GetService(serviceType);
    }

    /// <summary>
    /// Get all services of a type
    /// </summary>
    /// <param name="serviceType"></param>
    /// <returns></returns>
    public IEnumerable<object> GetServices(Type serviceType)
    {
        return this.serviceProvider.GetServices(serviceType);
    }
}

오토팩을 사용하는 것을 추천합니다. unity, inject와 같은 또 다른 swk가 있습니다. 벤치마크 오토팩은 뛰어난 성능을 가지고 있습니다.

http://www.palmmedia.de/blog/2011/8/30/ioc-container-benchmark-performance-comparison

다음은 MVC와의 통합입니다(모든 클래스에서 작동).

http://docs.autofac.org/en/latest/integration/mvc.html

ASP하는 가장 한 ASP.NET MVC 5라는 입니다.Unity.

인터넷에서 이에 대한 많은 리소스를 찾을 수 있으며, 여기에서 제공되는 공식 문서인 Unity를 사용한 종속성 주입에 대한 개발자 가이드를 읽는 것으로 시작할 수 있습니다.

또한 종속성 주입은 컨트롤러로만 제한됩니까? 아니면 모든 클래스에서 작동할 수 있습니까?

구현과 관련된 인터페이스를 등록하는 한(IoC 패턴을 활용하려면) 프로젝트의 모든 클래스에서 작동합니다. 그러면 생성자에 인터페이스 인스턴스를 추가하기만 하면 됩니다.

이 비디오에서는 Microsoft MVP가 AutoFac과 함께 MVC5의 종속성 주입을 시연합니다.설정 방법에 대한 매우 명확한 설명:

종속성 주입 MVC5 데모

소스 코드는 GitHub에서 사용할 수 있습니다.

From here https://scottdorman.blog/2016/03/17/통합-asp-net-core-dependency-in-mvc-4/

이 대사가 절 구해줬어요

    services.AddControllersAsServices(typeof(Startup).Assembly.GetExportedTypes()
      .Where(t => !t.IsAbstract && !t.IsGenericTypeDefinition)
      .Where(t => typeof(IController).IsAssignableFrom(t) 
       || t.Name.EndsWith("Controller", StringComparison.OrdinalIgnoreCase)));

를 사용하는 것이 좋습니다.Windsornuget 패키지를 설치하여Castle Windsor MVC Bootstrapper그러면 당신은 다음을 구현하는 서비스를 만들 수 있습니다.IWindsorInstaller다음과 같은 것:

public class ServiceRegister : IWindsorInstaller
{
    public void Install(Castle.Windsor.IWindsorContainer container,
    Castle.MicroKernel.SubSystems.Configuration.IConfigurationStore store)
    {
        SomeTypeRequiredByConstructor context = new SomeTypeRequiredByConstructor ();

        container.Register(
            Component
                .For<IServiceToRegister>()
                .ImplementedBy<ServiceToRegister>().
             DependsOn(Dependency.OnValue<SomeTypeRequiredByConstructor>(context))//This is in case your service has parametrize constructoe
                .LifestyleTransient());
    }
}

컨트롤러 내부에는 다음과 같은 것이 있습니다.

public class MyController 
{
    IServiceToRegister _serviceToRegister;

    public MyController (IServiceToRegister serviceToRegister)
    {
        _serviceToRegister = serviceToRegister;//Then you can use it inside your controller
    }
}

그리고 기본적으로 라이브러리는 컨트롤러에 올바른 서비스를 전송하는 것을 처리합니다.install()ServiceRegister그것이 구현되기 때문에 시작할 수 있습니다.IWindsorInstaller

이 스레드에서 시작하여 Microsoft 사용 방법을 알아봅니다.내선 번호.의존제 ASP.NET MVC 5 프로젝트에 주입하고, 읽고, 노력하고, 실패하면서, 저는 마침내 여러분들에게 뻔뻔스럽게 제안하고 싶은 해결책을 생각해냈습니다.

저는 스콧 도먼의 예제 코드인 David Fowler의 요지를 수집했고, ASP.NET MVC "Classic"에서 ASP.NET Core의 시작을 시뮬레이션할 수 있는 라이브러리를 만들기 위해 저만의 향신료를 약간 추가했습니다.

자세한 내용은 GitHub for Arex388 저장소를 참조하십시오.AsNet.Mvc.시작.관심이 있으시다면 제 블로그 게시물을 통해 이에 대한 내용을 확인하실 수도 있습니다(로드되지 않을 경우, 로드될 때까지 업데이트하십시오. 서버가 문제를 일으켜 조사할 시간이 없었습니다...).누군가에게 도움이 되길 바랍니다!

언급URL : https://stackoverflow.com/questions/43311099/how-to-create-dependency-injection-for-asp-net-mvc-5

반응형