user1482886
user1482886

Reputation: 1

Define class dynamically with Service Locator - Asp.Net Core

I am working with Asp.Net Core application. I have two classes namely Online and Offline. I have created interface and defined the methods in these two classes. Based on the need I have to connect to anyone of these two classes.

Previously when I worked in Asp.Net MVC, I have used unity container and Service Locator to specify the class name in XML file for invoking the class dynamically (between online and offline).

Now I want to implement the same with Asp.Net core. But I am not sure how to specify the class name outside for method invocation. Kindly help.

Thanks

Upvotes: 0

Views: 419

Answers (2)

user1482886
user1482886

Reputation: 1

After lot of brainstroming, I found the below solution

Create a class for ServiceLocator

public class ServiceLocator
{
    private ServiceProvider _currentServiceProvider;
    private static ServiceProvider _serviceProvider;

    public ServiceLocator(ServiceProvider currentServiceProvider)
    {
        _currentServiceProvider = currentServiceProvider;
    }

    public static ServiceLocator Current
    {
        get
        {
            return new ServiceLocator(_serviceProvider);
        }
    }

    public static void SetLocatorProvider(ServiceProvider serviceProvider)
    {
        _serviceProvider = serviceProvider;
    }

    public object GetInstance(Type serviceType)
    {
        return _currentServiceProvider.GetService(serviceType);
    }

    public TService GetInstance<TService>()
    {
        return _currentServiceProvider.GetService<TService>();
    }
}

Step 2: Create interface and inherit in the classes and define the interface methods

Step 3: Define class name in appSettings.json and read the values in startup.cs

 public void ConfigureServices(IServiceCollection services)
    {
        //reading from appSettings.json
        string strClassName = Configuration["DependencyInjection:className"];

        if (strClassName == "OnlineData")
            services.AddTransient<<<InterfaceName>>, <<OnlineClassName>>>();
        if (strClassName == "OfflineData")
            services.AddTransient<<<InterfaceName>>, <<OfflineClassName>>>();
    }

Step 4: Create object for the dynamic class inside controller/action method

InterfaceNamemyService = ServiceLocator.Current.GetInstance<>();

Upvotes: 0

cdev
cdev

Reputation: 5361

In .net core dependency injection is in built. You don't need unity or any other any more. https://learn.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-5.0 You can achieve what you want by using a little tweak.

//// classes

public interface IFileUploadContentProcess
{
    IEnumerable<StoreOrder> ProcessUploads(IFormFile file);
}

public class ProcessExcelFiles : IFileUploadContentProcess
{
    public IEnumerable<StoreOrder> ProcessUploads(IFormFile file)
    {
        throw new NotImplementedException();
    }
}

public class ProcessCsvFiles : IFileUploadContentProcess
{
    public IEnumerable<StoreOrder> ProcessUploads(IFormFile file)
    {
        throw new NotImplementedException();
    }
}


//// register it
public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers();

    services.AddTransient<IStoreOrderService, StoreOrderService>();

    services.AddTransient<ProcessExcelFiles>();
    services.AddTransient<ProcessCsvFiles>();

    // Add resolvers for different sources here
    services.AddTransient<Func<string, IFileUploadContentProcess>>(serviceProvider => key =>
    {
        return key switch
        {
            "xlsx" => serviceProvider.GetService<ProcessExcelFiles>(),
            _ => serviceProvider.GetService<ProcessCsvFiles>(),
        };
    }); 
}

//use it

public class StoreOrderService : IStoreOrderService
{
    private readonly Func<string, IFileUploadContentProcess> _fileUploadContentProcess;

    public StoreOrderService(Func<string, IFileUploadContentProcess> fileUploadContentProcess)
    {
        _fileUploadContentProcess = fileUploadContentProcess;
    }
        
    public async Task<IEnumerable<StoreOrder>> UploadStoreOrdersAsync(IFormFile file)
    {
        //// passing csv to process csv type(default), if xlsx, pass xlsx
        var records = _fileUploadContentProcess("csv").ProcessUploads(file);
        return records;
    }
}

Upvotes: 1

Related Questions