net c# .net wcf service .net-core

c# - ¿Qué reemplaza a WCF en.Net Core?



wcf net core 2 (4)

Así que de mi investigación, la mejor solución no tiene las clases de proxy generadas automáticamente. Esta mejor solución es crear un servicio RESTful y serializar el cuerpo de la respuesta en objetos modelo. Donde los modelos son los objetos de modelo habituales que se encuentran en el patrón de diseño MVC.

Gracias por sus respuestas

Estoy acostumbrado a crear una aplicación de consola de .Net Framework y exponer una función Add(int x, int y) través de un servicio WCF desde cero con Class Library (.Net Framework). Luego uso la aplicación de consola para llamar a esta función desde el servidor.

Sin embargo, si uso la aplicación de consola (.Net Core) y una biblioteca de clases (.Net Core), System.ServiceModel no está disponible. He hecho algo de Google pero no he descubierto qué "reemplaza" a WCF en este caso.

¿Cómo expongo una función Add(int x, int y) dentro de una biblioteca de clases a una aplicación de consola, todo dentro de .Net Core? Veo System.ServiceModel.Web y, como esto intenta ser multiplataforma, ¿tengo que crear un servicio RESTful?


Hay un puerto .NET Core disponible: github.com/dotnet/wcf Todavía está en vista previa, pero lo están desarrollando activamente.


Puede usar gRPC para hospedar servicios web dentro de la aplicación central de .NET.

Introducción

  1. gRPC es un marco RPC de código abierto y alto rendimiento desarrollado inicialmente por Google.
  2. El marco se basa en un modelo cliente-servidor de llamadas a procedimientos remotos. Una aplicación cliente puede llamar directamente a métodos en una aplicación de servidor como si fuera un objeto local.

Ejemplo

Código del servidor

class Program { static void Main(string[] args) { RunAsync().Wait(); } private static async Task RunAsync() { var server = new Grpc.Core.Server { Ports = { { "127.0.0.1", 5000, ServerCredentials.Insecure } }, Services = { ServerServiceDefinition.CreateBuilder() .AddMethod(Descriptors.Method, async (requestStream, responseStream, context) => { await requestStream.ForEachAsync(async additionRequest => { Console.WriteLine($"Recieved addition request, number1 = {additionRequest.X} --- number2 = {additionRequest.Y}"); await responseStream.WriteAsync(new AdditionResponse {Output = additionRequest.X + additionRequest.Y}); }); }) .Build() } }; server.Start(); Console.WriteLine($"Server started under [127.0.0.1:5000]. Press Enter to stop it..."); Console.ReadLine(); await server.ShutdownAsync(); } }

Codigo del cliente

class Program { static void Main(string[] args) { RunAsync().Wait(); } private static async Task RunAsync() { var channel = new Channel("127.0.0.1", 5000, ChannelCredentials.Insecure); var invoker = new DefaultCallInvoker(channel); using (var call = invoker.AsyncDuplexStreamingCall(Descriptors.Method, null, new CallOptions{})) { var responseCompleted = call.ResponseStream .ForEachAsync(async response => { Console.WriteLine($"Output: {response.Output}"); }); await call.RequestStream.WriteAsync(new AdditionRequest { X = 1, Y = 2}); Console.ReadLine(); await call.RequestStream.CompleteAsync(); await responseCompleted; } Console.WriteLine("Press enter to stop..."); Console.ReadLine(); await channel.ShutdownAsync(); } }

Clases compartidas entre cliente y servidor

[Schema] public class AdditionRequest { [Id(0)] public int X { get; set; } [Id(1)] public int Y { get; set; } } [Schema] public class AdditionResponse { [Id(0)] public int Output { get; set; } }

Descriptores de servicio

using Grpc.Core; public class Descriptors { public static Method<AdditionRequest, AdditionResponse> Method = new Method<AdditionRequest, AdditionResponse>( type: MethodType.DuplexStreaming, serviceName: "AdditonService", name: "AdditionMethod", requestMarshaller: Marshallers.Create( serializer: Serializer<AdditionRequest>.ToBytes, deserializer: Serializer<AdditionRequest>.FromBytes), responseMarshaller: Marshallers.Create( serializer: Serializer<AdditionResponse>.ToBytes, deserializer: Serializer<AdditionResponse>.FromBytes)); }

Serializador / Deserializador

public static class Serializer<T> { public static byte[] ToBytes(T obj) { var buffer = new OutputBuffer(); var writer = new FastBinaryWriter<OutputBuffer>(buffer); Serialize.To(writer, obj); var output = new byte[buffer.Data.Count]; Array.Copy(buffer.Data.Array, 0, output, 0, (int)buffer.Position); return output; } public static T FromBytes(byte[] bytes) { var buffer = new InputBuffer(bytes); var data = Deserialize<T>.From(new FastBinaryReader<InputBuffer>(buffer)); return data; } }

Salida

Ejemplo de salida del cliente

Salida del servidor de muestra

Referencias

  1. https://blogs.msdn.microsoft.com/dotnet/2018/12/04/announcing-net-core-3-preview-1-and-open-sourcing-windows-desktop-frameworks/
  2. https://grpc.io/docs/
  3. https://grpc.io/docs/quickstart/csharp.html
  4. https://github.com/grpc/grpc/tree/master/src/csharp

Puntos de referencia

  1. http://csharptest.net/787/benchmarking-wcf-compared-to-rpclibrary/index.html

WCF no es compatible con .NET Core ya que es una tecnología específica de Windows, mientras que .NET Core se supone que es multiplataforma. Si está implementando la comunicación entre procesos, considere probar este proyecto . Permite crear servicios en estilo WCF:

Paso 1 - Crear contrato de servicio

public interface IComputingService { float AddFloat(float x, float y); }

Paso 2: Implementar el servicio.

class ComputingService : IComputingService { public float AddFloat(float x, float y) { return x + y; } }

Paso 3 - Alojar el servicio en la aplicación de consola

class Program { static void Main(string[] args) { // configure DI IServiceCollection services = ConfigureServices(new ServiceCollection()); // build and run service host new IpcServiceHostBuilder(services.BuildServiceProvider()) .AddNamedPipeEndpoint<IComputingService>(name: "endpoint1", pipeName: "pipeName") .AddTcpEndpoint<IComputingService>(name: "endpoint2", ipEndpoint: IPAddress.Loopback, port: 45684) .Build() .Run(); } private static IServiceCollection ConfigureServices(IServiceCollection services) { return services .AddIpc() .AddNamedPipe(options => { options.ThreadCount = 2; }) .AddService<IComputingService, ComputingService>(); } }

Paso 4 - Invoque el servicio desde el proceso del cliente.

IpcServiceClient<IComputingService> client = new IpcServiceClientBuilder<IComputingService>() .UseNamedPipe("pipeName") // or .UseTcp(IPAddress.Loopback, 45684) to invoke using TCP .Build(); float result = await client.InvokeAsync(x => x.AddFloat(1.23f, 4.56f));