循环引用问题Singleton

时间:2010-12-30 10:26:19

标签: c# c#-4.0 singleton circular-reference

我正在尝试创建一个类似下面的Singleton类,其中MyRepository位于单独的DAL项目中。它导致我的循环引用问题,因为GetMySingleTon()方法返回MySingleTon类并需要它的访问权限。同样,我需要在MyRepository类的构造函数中访问MySingleTon

  public class MySingleTon
  {
    static MySingleTon()
    {
      if (Instance == null)
      {
        MyRepository rep = new MyRepository();
        Instance = rep.GetMySingleTon();
      }
    }
    public static MySingleTon Instance { get; private set; }
    public string prop1 { get; set; }
    public string prop2 { get; set; }
  }

更新:我做得非常错误。 我认为不需要任何单身人士。现在我在第三个项目中创建了一个具有静态属性的类,我将它设置一次并随处访问它。它现在解决了我的问题。

感谢大家的回答。

4 个答案:

答案 0 :(得分:1)

存储库不应返回单个对象,存储库用于访问数据而不返回单个对象。您的存储库本身可以是单例,但我不推荐它,我也不建议使用存储库为类使用单例。在您拥有的代码中,似乎存储库需要知道“业务层”,这一切都搞砸了,关系应该只有一种方式。我会把它重写为:

public class MySingleTon
{
    private MySingleTon()
    {
       // You constructor logic, maybe create a reference 
       // to your repository if you need it
    }

    private static MySingleTon _instance;
    public static MySingleTon Instance { 
       get
       {
          if(_instance == null)
             _instance = new MySingleTon();
          return _instance;
       }
    }
    public string prop1 { get; set; }
    public string prop2 { get; set; }
}

我不推荐我的解决方案,但它应该解决你的问题。我建议的是调查依赖注入和控制反转,因为你的设计似乎有点不对劲。看看NInject

编辑:另外一件事,为什么你的单身人士有几个公开的属性?单例不应该暴露它应该只暴露函数的属性,并且应该主要在具有像Math这样的实用程序类或像记录器这样的真正单例时使用。

答案 1 :(得分:0)

虽然,创建这样的类内部并不好,但我不知道这背后的原因是什么。

但您可以执行类似下面的代码

创建一个名为Public Interface的项目,并使用要从MyRepository类公开的公共函数定义一个接口IMyRepository。

在单例类中创建一个返回IMyRepository的公共属性,也可以在程序集外部设置。

现在,您需要从引用singelton程序集的程序集中显式设置此属性,并假设您可以从其他程序集创建MyRepository类的对象。

请注意:上述解决方案只是打破循环引用而不是最佳解决方案的技巧。

答案 2 :(得分:0)

虽然在类本身中具有单例访问器属性是一种通常使用的快捷方式,但在更复杂的情况下,当您需要处理多个相关类的实例时,它可能证明是错误的方式。问题在于将问题混合在一个类中。

您的MySingleton类应该是某些MyClass,其实现方式通常不依赖于运行时存在的实例数。同样,MyRepository应能够管理并提供任意数量的MyClass个实例。您将只处理MyClass的单个实例的事实可以封装到一个单独的工厂(或访问器或任何您称之为)的类中,它将MyClassMyRepository绑定在一起。

因此,请尝试以下列方式重新考虑您的设计(原理图):

public class MyClass { ... }

public class MyRepository
{
    public MyClass GetMyClassInstance(...);
}

public static class MyClassFactory
{
    public static MyClass SingletonInstance 
    { 
        get 
        { 
            if (singletonInstance == null) 
                singletonInstance = myRepository.GetMyClassInstance(...);
            return singletonInstance;
        }
    }
}

剩下的问题是myRepository来自哪里。例如,它可以在程序启动时创建,并作为成员字段配置到MyclassFactory

在一天结束时,如果考虑使用控制容器的反转,可以使很多事情变得容易。下一步也将转向基于接口的设计。这为您提供了另一层抽象,并在实现的可互换性方面提供了更大的灵活性。

答案 3 :(得分:0)

除了Saurabh的代码之外,您还将通过以下方式更改Singleton类:

public class MySingleTon
  {
    static MySingleTon()
    {
      if (Instance == null)
      {
        Instance = new MySingleTon();
      }
    }

    private MySingleTon(){}

    public static MySingleTon Instance { get; private set; }
    public IMyRepository MyRepository{ get; set ;}

  }