Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
131 views
in Technique[技术] by (71.8m points)

c# - Transient and Scoped services consuming a singleton data source

I am trying to learn dependency inversion and IOC. In the process, I have hit a wall.

This is what I understand about DI principle -> high-level classes are based on abstractions and not implementations.

All good.

So keeping the above in mind. I have the following example.

public interface IServiceA
{
   public void DoSomething();
}

public class ServiceA : IServiceAInterface
{
   IDataInterface dataSource;
   DataSourceType data;

   // omitted config injectino for brevity
   public ServiceA(IDataInterface _data)
   {
            dataSource = _dataSource;
            var dataSourceName = config.GetValue<string>("DataSourceName"); 
            data = dataSource.GetDataSource(dataSourceName);
   }

   public void doSomething()
   {
      data.doSomething();
   }
}
public interface IDataInterface
{
    public DataSourceType getDataSource(string ds);
}

public class DataAccessService : IDataInterface
{
        public DataSourceType GetDataSource(string dataSource)
        {
            if (dataSource == "InApp")
            {
                var source = new DataSourceType();
                return source;
            }
            else
            {
                return null;
            }
        }
}

The above is a service class which needs data to perform tasks which it gets from DataAccessService.

Now I am using an application class/model for persistence throughout the app lifetime. Therefore I have registered it as a singleton.

Startup.cs

public void ConfigureServices(IServiceCollection services)
{
    ---
    services.AddSingelton<IDataInterface,DataAccessService>();
    service.AddScoped<IServieAInterface,ServiceA>();
    ---
}

This does not work.

I hypothesize it is because, the parent service (service A) has a lesser lifetime than the child service (DataAccessService).

I have understood through this that service A is responsible for instantiation of the object.

However, I expected the IOC container to instantiate only one DataAccessService object and inject it to all services that need this.

Not sure why my assumption is wrong.

Based on the above hypothesis I tried the following:

public interface IDataInterface
{
}

public class DataAccessService : IDataInterface
{
    public DataSourceType dataSource;

    public DataAccessService(string ds)
    {
        if (ds == "InApp")
        {
            this.dataSource = new DataSourceType();
        }
        else
        {
            this.dataSource = null;
        }
    }
}

public class ServiceA: DataAccessService,IServceAInterface
{
    DatSourceTye data;
  
    public ServiceA():base("InApp")
    {
        config = _config;
        data = dataSource;
    }

    public void doSomething()
    {
      data.doSomething();
    }
}

Startup.cs

// Hoping to pass parameter through startup
services.AddSingleton<IDataInterface>(x =>
            ActivatorUtilities.CreateInstance<DataAccessService>(x, "InApp")
        );
service.AddScoped<IServieAInterface,ServiceA>();

I hoped the above would work, as here the DataAccessService is responsible for initialization.

But still a new DataAccessService object is created for every class.

I think, I have messed up my understanding about how the life times work. need help on this.

Also, what I am trying to achieve is a singleton data source on which different services act on throughout the application lifetime.

Transient and scoped services consuming a singleton data source. I think this should be possible

Is there something bad in terms of design in what I am trying to achieve?

question from:https://stackoverflow.com/questions/65869715/transient-and-scoped-services-consuming-a-singleton-data-source

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)
 public DataAccessService(string ds)
    {
        if (ds == "InApp")
        {
            this.dataSource = new DataSourceType();
        }
        else
        {
            this.dataSource = null;
        }
    }

This method in the data service was being called every time, I needed the data source. As this method is instantiating another class manually, though the service is singleton, every time the above method - DataAccessService was called , I was getting a new instance.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...