Eu gostaria de passar valores para o construtor da classe que implementa meu serviço.
No entanto, o ServiceHost permite apenas que eu passe o nome do tipo a ser criado, não quais argumentos passar ao seu construtor.
Gostaria de poder passar em uma fábrica que crie meu objeto de serviço.
O que descobri até agora:
- Comportamento de injeção de dependência WCF que é mais do que o que estou procurando e parece ser excessivamente complexo para minhas necessidades.
wcf
dependency-injection
factory-pattern
Ian Ringrose
fonte
fonte
Respostas:
Você precisará implementar uma combinação de costume
ServiceHostFactory
,ServiceHost
eIInstanceProvider
.Dado um serviço com esta assinatura de construtor:
Aqui está um exemplo que pode ativar o MyService:
Registre MyServiceHostFactory em seu arquivo MyService.svc ou use MyServiceHost diretamente no código para cenários de auto-hospedagem.
Você pode facilmente generalizar essa abordagem e, na verdade, alguns DI Containers já fizeram isso para você (sugestão: Windsor's WCF Facility).
fonte
protected
Não consigo chamá-la de Main ()dep
em cada InstanceProvider do contrato . Você poderia fazer:ImplementedContracts.Values.First(c => c.Name == "IMyService").ContractBehaviors.Add(new MyInstanceProvider(dep));
ondeIMyService
está uma interface de contrato seuMyService(IDependency dep)
. Portanto, injeteIDependency
apenas no InstanceProvider que realmente precisa dele.Você pode simplesmente criar uma instância de seu
Service
e passar essa instância para oServiceHost
objeto. A única coisa que você precisa fazer é adicionar um[ServiceBehaviour]
atributo para o seu serviço e marcar todos os objetos retornados com o[DataContract]
atributo.Aqui está um mock up:
e o uso:
Espero que isso facilite a vida de alguém.
fonte
InstanceContextMode.Single
).A resposta de Mark com o
IInstanceProvider
está correta.Em vez de usar o ServiceHostFactory personalizado, você também pode usar um atributo personalizado (digamos
MyInstanceProviderBehaviorAttribute
). Derive-oAttribute
, faça-o implementarIServiceBehavior
e implementar oIServiceBehavior.ApplyDispatchBehavior
método comoEm seguida, aplique o atributo à sua classe de implementação de serviço
A terceira opção: você também pode aplicar um comportamento de serviço usando o arquivo de configuração.
fonte
Trabalhei com a resposta de Mark, mas (pelo menos para meu cenário), era desnecessariamente complexo. Um dos
ServiceHost
construtores aceita uma instância do serviço, que você pode passar diretamente doServiceHostFactory
implementação.Para pegar carona no exemplo de Mark, seria assim:
fonte
instance
. Isso pode ou não afetar o desempenho. Se você deseja ser capaz de lidar com solicitações simultâneas, todo o gráfico de objeto deve ser thread-safe, ou você obterá um comportamento incorreto e não determinístico. Se você pode garantir a segurança do thread, minha solução é, de fato, desnecessariamente complexa. Se você não pode garantir isso, minha solução é necessária.Dane-se… Eu combinei os padrões de injeção de dependência e localizador de serviço (mas na maioria das vezes ainda é injeção de dependência e até ocorre no construtor, o que significa que você pode ter estado somente leitura).
As dependências do serviço são claramente especificadas no contrato de sua
Dependencies
classe aninhada . Se você estiver usando um contêiner IoC (um que ainda não conserte a bagunça do WCF para você), pode configurá-lo para criar aDependencies
instância em vez do serviço. Dessa forma, você obtém a sensação aconchegante de seu contêiner, ao mesmo tempo em que não precisa passar por muitos obstáculos impostos pelo WCF.Não vou perder o sono com essa abordagem. Nem deveria ninguém mais. Afinal, seu contêiner IoC é uma grande coleção estática de delegados que cria coisas para você. O que está adicionando mais um?
fonte
Estávamos enfrentando esse mesmo problema e o resolvemos da seguinte maneira. É uma solução simples.
No Visual Studio, basta criar um aplicativo de serviço WCF normal e remover sua interface. Deixe o arquivo .cs no lugar (apenas renomeie-o) e abra esse arquivo cs e substitua o nome da interface pelo seu nome de classe original que implementa a lógica de serviço (desta forma, a classe de serviço usa herança e substitui sua implementação real). Adicione um construtor padrão que chame os construtores da classe base, como este:
A classe base MyService é a implementação real do serviço. Esta classe base não deve ter um construtor sem parâmetros, mas apenas construtores com parâmetros que aceitam as dependências.
O serviço deve usar essa classe em vez do MyService original.
É uma solução simples e funciona perfeitamente :-D
fonte
Essa foi uma solução muito útil - especialmente para alguém que é um programador de WCF novato. Eu queria postar uma pequena dica para qualquer usuário que possa estar usando isso para um serviço hospedado no IIS. MyServiceHost precisa herdar WebServiceHost , não apenas ServiceHost.
Isso criará todas as ligações necessárias, etc. para seus pontos de extremidade no IIS.
fonte
Eu uso variáveis estáticas do meu tipo. Não tenho certeza se esta é a melhor maneira, mas funciona para mim:
Ao instanciar o host de serviço, faço o seguinte:
fonte