Pergunta

Estou implementando uma estrutura de notificação para um dos meus projetos. Como eu quero que seja muito genérico, o usuário pode usar várias camadas de transporte, para que ele realmente não precise se preocupar em usar um método de entrega (digamos WCF) ou outro (para o EG ActiveMQ). A interface que o usuário tem acesso é obviamente independente do método de entrega (WCF ou ActiveMQ). Ainda assim, as duas classes (consumidor e produtor) implementa singletons, então eles realmente usam construtores padrão (significando, sem parâmetros). Meu problema é que eu gostaria de ter um parâmetro, o método de entrega que o usuário deseja usar. Mas, até onde eu sei, o Singleton usa apenas construtores padrão? o que é normal, pois não deve haver sentido ao usar singletons com parâmetros. Então, quais são minhas opções aqui? Não criar um singleton? criar um método para definir o método de entrega?

Muito obrigado pela sua ajuda,

Sebastian

Foi útil?

Solução

Você certamente pode ter parâmetros com singletons, exceto em vez de passar o parâmetro em um construtor, você o está passando para o método getInstance (). Seu construtor substituído precisa ser privado, é claro, para uma verdadeira implementação de singleton. Meu exemplo foi escrito em Java, mas também se aplica ao C#.

Exemplo:

Singleton s = Singleton.getInstance(42);

No código Singleton:

private Singleton() {

}

private Singleton(int num) {
   //set num
}

public getInstance(int num) {
  //singleton code (calls the private non-default constructor if an object 
  //does not already exist) 
}

Outras dicas

Existem algumas estruturas de injeção de dependência como o Spring.net que podem ajudá -lo. Você pode passar efetivamente um parâmetro em um arquivo de configuração para o seu construtor singletons.

Link para um exemplo de estrutura de primavera

Posso sugerir que, se você tiver dois comportamentos diferentes necessários do seu singleton, você pode querer subclasse. Dessa forma, você obtém o comportamento que deseja chamando o Singleton do comportamento da classe que deseja.

Você pode fazer isso facilmente com uma estrutura de injeção de dependência. Eu tenho uma construção semelhante no meu projeto atual usando Mef. Tudo o que é necessário é usar as opções de injeção do construtor e adicionar esse conjunto e a montagem da dependência solicitada ao catálogo e ele a serve corretamente.

Outra opção é ter alguma forma de função inicializada que adota sua opção e constrói a instância do Singleton. Em vez de construí -lo no primeiro acesso, você pode construí -lo durante a chamada de inicialização. A desvantagem aqui é que você precisa inicializar seu singleton antes de usá -lo (normalmente no início do programa, usando um arquivo de configuração).

Uma opção semelhante, mas menos propensa a erros, é apenas ter a Singleton Lazy Initialize e dar uma opção "padrão". Permita que o chamador defina uma propriedade estática para alterar qual opção é construída; portanto, se estiver definido antes da construção do Singleton, você obterá um padrão diferente. Isso pode ser confuso, no entanto, desde novamente, você precisa definir a propriedade antes de acessar o Singleton, ou terá um comportamento inesperado.

Sei que é tarde para responder à pergunta original, mas eu apenas tive esse problema e aqui está como eu resolvi. Pode não ser o ideal, mas parece funcionar. Criei um método init que deve ser chamado antes de tentar usar a instância Singleton.

public void Init(/*parameters*/)
{
        if (_isInitialized)
        {
            throw new InvalidOperationException("Component is already initialized!");
        }
        //do your work here
}

Qualquer outro acesso à instância Singleton (as propriedades obtêm, definidas, chamadas de método) lançarão uma exceção de operação inválida, informando que o objeto não foi inicializado.

Eu acho que isso faz o que eu preciso, é menos confuso do que o GetInstance (Params), porque não há risco de entender mal o que o método faz. A desvantagem é que não lançará erros de tempo de compilação, mas a primeira corrida sem a inicialização realizada será uma exceção, por isso deve ser bom o suficiente.

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