Home > Blockchain >  How to resolve service inside a class that has no constructor?
How to resolve service inside a class that has no constructor?

Time:03-02

There are 3 solutions in my project.

  1. Api -> It just satisfies the requests and directs them to the Infrastructure project.
  2. Common -> contains commonly used models and utilities
  3. Infrastructure -> It meets the requests from API.

The infrastructure project has Interfaces, Services, and some classes (helpers, SaveManager).

I want to use one of the interfaces into a class that has no constructor. But I can't do this because there is no constructor for SaveManager class.I checked the Service Locator pattern, you should not use it because it is an antipattern. I check IServiceProvider bu again I cannot inject. How can I do this?

//model
public class Application
{
    //properties
}

//Contract
public interface IParameterService
{
    public List<Application> GetAllApplications();
}

//Service ->Implementation of Contract
public class ParameterService : IParametrerService
{

    public List<Application> GetAllApplications()
    {
        // returns application list
    }
}

//Helper

public class SaveManager
{

    public ValidatePackage()
    {
        //someCode

        //I want to call GetAllApplications() using IParameterService

        //someCode making some filtering and validations using response of GetAllApplications()
    }
}

CodePudding user response:

you have to follow DI rules. you can simply make new ParameterService() inside SaveManager Class but I guess your Service class need DbContext as well.

therefor,if you using SaveManager Class inside Controller or Razor Page, you can use something like Strategy Design Pattern:

1- Inject IParameterService in your Controller constructor:

    [Route("[controller]")]
    [ApiController]
    Public class YourController : ControllerBase
    {
        private readonly IParameterService _repo;
        public PlatformsController(IParameterService repo)
        {
            _repo= repo;
        }
    }

2- in the SaveManager Class -> ValidatePackage() method, pass IParameterService as method argument:

public class SaveManager
{

    public ValidatePackage(IParameterService  myservice)
    {
    }
}

3- now everything is done, when you call your ValidatePackage() method, you have to pass your Service and inside the method, you can simply access to all of methods there

CodePudding user response:

I think you could try Property injection with Autofac

At first,install these packages: enter image description here In Startup class:

add " services.Replace(ServiceDescriptor.Transient<IControllerActivator, ServiceBasedControllerActivator>());" to replace DefaultControllerActivator with ServiceBasedControllerActivator

then,add a metheod to regist the module we will define:

public void ConfigureContainer(ContainerBuilder builder)
        {
            
            builder.RegisterModule<BaseServiceRegisterModule>();
            builder.RegisterModule<PropertiesAutowiredModule>();
        }

complete the module:

public class BaseServiceRegisterModule : Autofac.Module
    {
        protected override void Load(ContainerBuilder builder)
        {
            // Register your own things directly with Autofac, like:
            builder.RegisterType<UserService>().As<IUserService>().InstancePerDependency().AsImplementedInterfaces();
        }
    }

    public class PropertiesAutowiredModule : Autofac.Module
    {
        protected override void Load(ContainerBuilder builder)
        {
            // get all controller types then accomplish  property  injection
            var controllerBaseType = typeof(ControllerBase);
            builder.RegisterAssemblyTypes(typeof(Program).Assembly)
                .Where(t => controllerBaseType.IsAssignableFrom(t) && t != controllerBaseType)
                .PropertiesAutowired(new AutowiredPropertySelector());
        }
    }

    public class AutowiredPropertySelector : IPropertySelector
    {
        public bool InjectProperty(PropertyInfo propertyInfo, object instance)
        {
            return propertyInfo.CustomAttributes.Any(it => it.AttributeType == typeof(AutowiredAttribute));
        }
    }

In controller:

[Autowired]
 private IUserService UserService { get; set; }

 public IActionResult Index()
        {
            var a = UserService.GetUser();
            return View();
        }

Result:

enter image description here

  • Related