Me gustaría pasar valores al constructor en la clase que implementa mi servicio.
Sin embargo, ServiceHost solo me permite pasar el nombre del tipo a crear, no qué argumentos pasar a su contrstructor.
Me gustaría poder pasar en una fábrica que crea mi objeto de servicio.
Lo que he encontrado hasta ahora:
- Comportamiento de inyección de dependencia de WCF que es más de lo que estoy buscando y parece ser demasiado complejo para mis necesidades.
wcf
dependency-injection
factory-pattern
Ian Ringrose
fuente
fuente
Respuestas:
Tendrá que aplicar una combinación de costumbre
ServiceHostFactory
,ServiceHost
yIInstanceProvider
.Dado un servicio con esta firma de constructor:
Aquí hay un ejemplo que puede activar MyService:
Registre MyServiceHostFactory en su archivo MyService.svc o use MyServiceHost directamente en el código para escenarios de autohospedaje.
Puede generalizar fácilmente este enfoque y, de hecho, algunos DI Containers ya lo han hecho por usted (señal: WCF Facility de Windsor).
fuente
protected
que no puedo llamarla yo mismo desde Main ()dep
en el InstanceProvider de cada contrato ? Podría hacer:ImplementedContracts.Values.First(c => c.Name == "IMyService").ContractBehaviors.Add(new MyInstanceProvider(dep));
dóndeIMyService
está una interfaz de contrato de suMyService(IDependency dep)
. Así que inyecteIDependency
solo en InstanceProvider que realmente lo necesita.Simplemente puede crear una instancia de su
Service
y pasar esa instancia alServiceHost
objeto. Lo único que tiene que hacer es agregar un[ServiceBehaviour]
atributo para su servicio y marcar todos los objetos devueltos con[DataContract]
atributo.Aquí hay una maqueta:
y el uso:
Espero que esto le facilite la vida a alguien.
fuente
InstanceContextMode.Single
).La respuesta de Mark con la
IInstanceProvider
es correcta.En lugar de utilizar ServiceHostFactory personalizado, también puede utilizar un atributo personalizado (por ejemplo
MyInstanceProviderBehaviorAttribute
). DerivarloAttribute
, hacer que implementeIServiceBehavior
e implementar elIServiceBehavior.ApplyDispatchBehavior
método comoLuego, aplique el atributo a su clase de implementación de servicio
La tercera opción: también puede aplicar un comportamiento de servicio utilizando el archivo de configuración.
fuente
Trabajé a partir de la respuesta de Mark, pero (al menos para mi escenario), era innecesariamente complejo. Uno de los
ServiceHost
constructores acepta una instancia del servicio, que puede pasar directamente desde laServiceHostFactory
implementación.Para aprovechar el ejemplo de Mark, se vería así:
fuente
instance
. Eso puede afectar o no al rendimiento. Si desea poder manejar solicitudes simultáneas, todo el gráfico de objeto debe ser seguro para subprocesos, o obtendrá un comportamiento incorrecto no determinista. Si puede garantizar la seguridad de los subprocesos, mi solución es, de hecho, innecesariamente compleja. Si no puede garantizar eso, se requiere mi solución.Al diablo ... Combiné la inyección de dependencia y los patrones del localizador de servicios (pero en su mayoría sigue siendo inyección de dependencia e incluso tiene lugar en el constructor, lo que significa que puede tener un estado de solo lectura).
Las dependencias del servicio están claramente especificadas en el contrato de su
Dependencies
clase anidada . Si está utilizando un contenedor de IoC (uno que aún no soluciona el problema de WCF), puede configurarlo para crear laDependencies
instancia en lugar del servicio. De esta manera, obtiene la cálida sensación difusa que le da su contenedor sin tener que pasar por demasiados aros impuestos por WCF.No voy a perder el sueño con este enfoque. Nadie más debería hacerlo. Después de todo, su contenedor de IoC es una colección grande, gruesa y estática de delegados que crea cosas para usted. ¿Qué agrega uno más?
fuente
Estábamos enfrentando este mismo problema y lo hemos resuelto de la siguiente manera. Es una solucion sencilla.
En Visual Studio, simplemente cree una aplicación de servicio WCF normal y elimine su interfaz. Deje el archivo .cs en su lugar (simplemente cámbiele el nombre) y abra ese archivo cs y reemplace el nombre de la interfaz con su nombre de clase original que implementa la lógica del servicio (de esta manera, la clase de servicio usa la herencia y reemplaza su implementación real). Agregue un constructor predeterminado que llame a los constructores de la clase base, como este:
La clase base MyService es la implementación real del servicio. Esta clase base no debe tener un constructor sin parámetros, sino solo constructores con parámetros que acepten las dependencias.
El servicio debe usar esta clase en lugar del MyService original.
Es una solución simple y funciona de maravilla :-D
fuente
Esta fue una solución muy útil, especialmente para alguien que es un codificador WCF novato. Quería publicar un pequeño consejo para cualquier usuario que pudiera estar usando esto para un servicio alojado en IIS. MyServiceHost necesita heredar WebServiceHost , no solo ServiceHost.
Esto creará todos los enlaces necesarios, etc. para sus puntos finales en IIS.
fuente
Utilizo variables estáticas de mi tipo. No estoy seguro de si esta es la mejor manera, pero me funciona:
Cuando creo una instancia del host de servicio, hago lo siguiente:
fuente