¿Cómo haría una persona para exponer método por método una API compuesta de varias clases a través de WCF sin usar un proyecto WCF?
Por ejemplo, digamos que tengo lo siguiente
public interface RainfallMonitor { [ExposeToWeb] void RecordRainfall(string county, float rainfallInches); [ExposeToWeb] float GetTotalRainfall(string county); void ClearRainfall(string county); }Entiendo que podría crear una biblioteca de servicios WCF como de costumbre y simplemente agregar un servicio WCF llamado "RainfallMonitor".
Lo que estoy explorando es... ¿es posible/razonable generar de alguna manera todo el código relacionado con WCF en tiempo de compilación para una API completa sin realmente hacer que las clases sean servicios WCF? Posiblemente usando atributos como ExposeToWeb para indicar qué métodos exponer a través de los servicios. La resultante funcionaría así:
RainfallAPIRainfallService automáticamente.Esencialmente:
Para aclarar: no estoy preguntando sobre la generación automática del código auxiliar del cliente, estoy preguntando sobre la creación de servicios en el lado del servidor.
Recientemente soy el jefe de esta biblioteca: Fody . Según tengo entendido, permite conectarse al proceso de compilación e inyectar IL en el ensamblaje. No estoy completamente seguro de cómo funciona, pero podría ser posible buscar a través de IL, encontrar todos los métodos con el atributo ExposeToWeb y usarlo para emitir el contrato para el servicio WCF en el ensamblado.
Pero, por otro lado, si ya está agregando atributos a la clase, ¿por qué no simplemente agregar los atributos WFC correctos para comenzar y luego usar SvcUtil para generar los contratos en la compilación posterior?
EDITAR: aquí hay un ejemplo de cómo podría usar svcutil :
C#:
[ServiceContract] public interface IRainfallMonitor { [OperationContract] void RecordRainfall(string county, float rainfallInches); } public class RainfallMonitor : IRainfallMonitor { public void RecordRainfall(string county, float rainfallInches) { // code } }PowerShell posterior a la compilación:
$svcutil = "C:\Program Files (x86)\Microsoft SDKs\Windows\v8.0A\bin\NETFX 4.0 Tools\SvcUtil.exe" $csc = "C:\Windows\Microsoft.NET\Framework\v4.0.30319\csc.exe" $assembly = "bin/debug/ProjectWithoutWCF.dll" $service = "ProjectWithoutWCF.RainfallMonitor" $outputns = "ProjectWithoutWCF.RainfallMonitor.Service" $outputdir = "bin/debug" md svcutil_tmp cd svcutil_tmp & $svcutil /serviceName:"$service" "../$assembly" & $svcutil *.wsdl *.xsd /importxmltypes /out:"output.cs" /n:"*,$outputns" & $csc /target:library /out:$outputns.dll "output.cs" cp "$outputns.dll" "../$outputdir" cp output.config "../$outputdir/$outputns.dll.config" cd .. rm -r .\svcutil_tmpy necesitará algo como esto en la configuración de su proyecto:
<system.serviceModel> <services> <service name="ProjectWithoutWCF.RainfallMonitor" > <endpoint address="" binding="basicHttpBinding" contract="ProjectWithoutWCF.IRainfallMonitor"> </endpoint> </service> </services> </system.serviceModel> Es un poco complicado y lo más probable es que necesite algunos ajustes en el script y la configuración. Pero el resultado es que tiene un archivo ProjectWithoutWCF.RainfallMonitor.Service.dll con los contratos de servicio de WCF.
Para su pregunta sobre "Lo que estoy explorando es... ¿es posible/razonable generar de alguna manera todo el código relacionado con WCF en tiempo de compilación para una API completa sin realmente hacer que las clases sean servicios de WCF?", hay opciones, pero todos tomarán mucho trabajo.
Debería escribir una aplicación/biblioteca de generación de código que utilice clases como CSharpCodeProvider (también hay una para VB) y reflexión para inspeccionar su biblioteca como un paso posterior a la compilación, compilar el código que desea en la memoria y guardarlo apagado como un archivo DLL.
Esta aplicación necesitaría encontrar un atributo personalizado que cree que indique que debe ser un servicio WCF y generar código WCF según las reglas que defina.
En efecto, necesita escribir código utilizando el modelo CodeDOM , lo que requiere pensar en el código de una manera muy diferente. No todo el mundo es capaz de abstraer su pensamiento a ese nivel.
Tenga en cuenta que al utilizar el modelo CodeDOM, puede superar algunos de los problemas que no mencionan los puntos, como la necesidad de serialización para los contratos de datos. Esto podría agregarse y su biblioteca de reflexión basada en CodeDOM generará una nueva DLL.
A través de un diseño cuidadoso y bastante trabajo, es posible lograr el resultado que está buscando. Es solo un camino oscuro con muchas trampas para llegar allí.
Sí, esto se puede hacer, con un esfuerzo moderado utilizando las herramientas adecuadas. Si tiene Visual Studio, ya tiene el generador de código T4 de Microsoft. Le permite generar código escribiendo "plantillas de texto", que recuerdan mucho a la sintaxis RAZOR de ASP.NET. Con T4, puede crear instancias de sus clases existentes y usar la reflexión para leer todos los nombres de clases y firmas de métodos y, en última instancia, generar sus servicios WCF. ¡No es tan dificil!
Aquí hay una plantilla T4 de muestra del tutorial de Oleg Sych :
<#@ template language=“C#v3.5” #> <#@ output extension=“SQL” #> <#@ assembly name=“Microsoft.SqlServer.ConnectionInfo” #> <#@ assembly name=“Microsoft.SqlServer.Smo” #> <#@ import namespace=“Microsoft.SqlServer.Management.Smo” #> <# Server server = new Server(); Database database = new Database(server, “Northwind”); Table table = new Table(database, “Products”); table.Refresh(); #> create procedure <#= table.Name #>_Delete <# PushIndent(”\t”); foreach (Column column in table.Columns) { if (column.InPrimaryKey) WriteLine(”@” + column.Name + ” ” + column.DataType.Name); } PopIndent(); #> as delete from <#= table.Name #> where <# PushIndent(”\t\t”); foreach (Column column in table.Columns) { if (column.InPrimaryKey) WriteLine(column.Name + ” = @” + column.Name); } PopIndent(); #>La salida se vería así:
create procedure Products_Delete @ProductID int as delete from Products where ProductID = @ProductIDPor supuesto, su ejemplo, usaría la reflexión en su biblioteca de clases existente en lugar de consultas sql. Los servicios de WCf que genera pueden simplemente llamar a su biblioteca existente, de modo que no tenga que copiar toda la lógica de dominio real.
MSDN