使用单例数据源的瞬态和作用域服务

Posted

技术标签:

【中文标题】使用单例数据源的瞬态和作用域服务【英文标题】:Transient and Scoped services consuming a singleton data source 【发布时间】:2021-04-28 08:52:34 【问题描述】:

我正在尝试学习依赖倒置和 IOC。在这个过程中,我碰壁了。

这就是我对 DI 原则的理解 -> 高级类基于抽象而不是实现。

一切都好。

因此请牢记上述内容。我有下面的例子。

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;
            
        

上面是一个服务类,它需要数据来执行它从DataAccessService获取的任务。

现在我正在使用应用程序类/模型在整个应用程序生命周期中保持持久性。因此我将其注册为单例。

Startup.cs

public void ConfigureServices(IServiceCollection services)

    ---
    services.AddSingelton<IDataInterface,DataAccessService>();
    service.AddScoped<IServieAInterface,ServiceA>();
    ---

这不起作用。

我假设这是因为父服务(服务 A)的生命周期比子服务(DataAccessService)的生命周期短。

我由此了解到服务 A 负责对象的实例化。

但是,我希望 IOC 容器仅实例化一个 DataAccessService 对象并将其注入所有需要此对象的服务。

不知道为什么我的假设是错误的。

基于上述假设,我尝试了以下方法:

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>();

我希望上面的方法可以工作,因为这里DataAccessService 负责初始化。

但仍然会为每个类创建一个新的 DataAccessService 对象。

我想,我搞砸了我对生命周期如何运作的理解。 在这方面需要帮助。

另外,我想要实现的是一个单一的数据源,不同的服务在整个应用程序生命周期中都在作用于它。

使用单例数据源的瞬态和范围服务。我认为这应该是可能的

我想要实现的设计在设计方面有什么不好的地方吗?

【问题讨论】:

完全有可能,您需要明确了解实际发生的情况。 Transient 和 Scoped 可以使用单例服务,但反之则不行。这不仅有可能,而且非常普遍。请edit 这个并附上minimal reproducible example。 如果加上错误信息就好了.. 没有收到任何错误,每次请求都会获取一个新实例。让我用更多代码编辑问题:) 在这里,我将 DataAccessService 注册为 Singelton 类,其余为 Transient,但 ApplicationDataSource 类在每个请求中都不断被重新实例化,因此我在每个请求中都获得了新对象。然而,让一切都很好。 发现我的错误,问题是 -> 我正在使用数据服务来获取数据源的实例。该服务是构造函数注入的。但是,为了从服务中获取数据源,我实际上是在其中一种服务方法中手动实例化数据源类。因此,尽管该服务是单例的,但每次我调用它的 GetDataSource 方法时,都会给我一个新实例。将关闭问题,ty :) 【参考方案1】:
 public DataAccessService(string ds)
    
        if (ds == "InApp")
        
            this.dataSource = new DataSourceType();
        
        else
        
            this.dataSource = null;
        
    

数据服务中的这个方法每次都被调用,我需要数据源。 由于此方法是手动实例化另一个类,虽然服务是单例的, 每次调用上述方法 - DataAccessService 时,我都会得到一个新实例。

【讨论】:

以上是关于使用单例数据源的瞬态和作用域服务的主要内容,如果未能解决你的问题,请参考以下文章

Grails 域中的瞬态属性

数据未保存:对象引用了未保存的瞬态实例 - 在刷新之前保存瞬态实例 [重复]

如何通过 UNO 存储每个打开文档的瞬态数据?

如何在 ASP.NET Core 中使控制器作用域或单例而不是瞬态?

CoreData 中的瞬态属性

对象引用未保存的瞬态实例?