Pergunta

Eu tenho um singleton que usa o "estático readonly T instância = new T ();" padronizar. No entanto, corri para um caso em que T é descartável, e na verdade tem de ser eliminados para testes de unidade. Como posso modificar esse padrão para apoiar um Singleton descartável?

A interface eu gostaria é algo como:

var x = Foo.Instance;
var y = Foo.Instance; // x == y
...
x.Release(); // this causes the next Foo.Instance to return a fresh object
             // also, it assumes no further operations on x/y will be performed.

Nota -. O padrão tem que ser thread-safe, é claro

Editar - com a finalidade de código de produção, este é um verdadeiro singleton. A coisa é que ele bloqueia alguns arquivos, e assim para limpeza em testes de unidade temos que eliminá-lo.

Eu também preferiria um padrão que pode ser reutilizado, se possível.

Foi útil?

Solução

Mark Release como internal e usar o atributo InternalsVisibleTo para expô-lo apenas para testar a sua unidade de montagem. Você pode fazer isso, ou se você é alguém cauteloso em sua própria montagem vai chamá-lo, você pode marcá-lo como private e acessá-lo usando a reflexão.

Use um finalizador na sua singleton que chama o método Dispose na instância singleton.

No código de produção, apenas o descarregamento de um AppDomain fará com que a disposição do Singleton. No código de teste, você pode iniciar uma chamada para Release si mesmo.

Outras dicas

Nesse ponto eu não acho que eu realmente considero que seja um solteirão mais, para ser honesto.

Em particular, se um cliente usa um singleton eles realmente não vai esperar que eles têm de dispor dela, e eles ficaria surpreso se alguém fez.

Qual é o seu código de produção vai fazer?

EDIT: Se você realmente, realmente preciso disso para testes de unidade e única para testes de unidade (que soa questionável em termos de design, para ser franco), então você poderia sempre mexer com o campo usando a reflexão . Seria mais agradável para descobrir se ele deve realmente ser um singleton ou se deve realmente ser descartável embora -. Os dois muito raramente andam juntos

Singletons não deve ser descartável. Período. Se alguém chama Descarte prematuramente, sua aplicação é parafusado até que ele reinicia.

 public class Foo : IDisposable
  { [ThreadStatic] static Foo _instance = null;

    private Foo() {IsReleased = false;}

    public static Foo Instance
     { get
        { if (_instance == null) _instance = new Foo();
          return _instance;
        }
     }

    public void Release()
     { IsReleased = true;
       Foo._instance = null;
     }

    void IDisposable.Dispose() { Release(); }

    public bool IsReleased { get; private set;}

  }

Se os implementos classe IDisposable (como você implica que ele faz), então basta chamar x.Dispose ()

Você pode usar um singleton preguiçoso aninhada (Veja aqui ) com alguma modificações simples:

public sealed class Singleton : IDisposable
{
    Singleton()
    {
    }

    public static Singleton Instance
    {
        get
        {
            if (!Nested.released)
                return Nested.instance;
            else
                throw new ObjectDisposedException();
        }
    }

    public void Dispose()
    {
         disposed = true;
         // Do release stuff here
    }

    private bool disposed = false;

    class Nested
    {
        // Explicit static constructor to tell C# compiler
        // not to mark type as beforefieldinit
        static Nested()
        {
        }

        internal static readonly Singleton instance = new Singleton();
    }
}

Lembre-se de jogar ObjectDisposedException em todos os métodos públicos / propriedades do objeto se ele foi descartado.

Você deve também, fornecer um método finalizador para o objeto, no caso Descarte não obter chamado. Veja como implementar corretamente IDisposable aqui .

Para testes de unidade, você poderia usar uma instância de "manual" (mas você precisa encontrar uma maneira para instanciar o objeto).

No seu caso, provavelmente é melhor você usar o padrão de fábrica (abstract / método - o que for melhor para o seu caso)., Combinada com uma Singleton

Se você quiser testar se o singleton dispôs corretamente os objetos usados ??(em teste de unidade), então usar o método de fábrica, caso contrário, usar o padrão Singleton.

A propósito, se você não tem acesso ao código-fonte única ou você não tem permissão para modificá-lo, seria melhor envolvê-la para outro Singleton, e fornecer toda a lógica do novo (mais como um proxy). Parece exagero, mas poderia ser uma solução viável.

Além disso, a fim de ser capaz de controlar o acesso a ele, proporcionar uma fábrica, e deixar que os clientes obter o novo objeto somente se o objeto não foi descartado.

Outra opção para fazer um Singleton descartável é a utilização de SandCastle [Singleton] atribute para sua classe, em seguida, quadro Castelo cuida de eliminar todos Singleton descartável objetos

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top