Estou acostumado a criar um aplicativo de console .Net Framework e expor uma Add(int x, int y)
função por meio de um serviço WCF do zero com a biblioteca de classes (.Net Framework). Em seguida, uso o aplicativo de console para chamar de proxy essa função no servidor.
No entanto, se eu usar o aplicativo de console (.Net Core) e uma biblioteca de classes (.Net Core), o System.ServiceModel não estará disponível. Eu fiz algumas pesquisas no Google, mas não descobri o que "substitui" o WCF neste caso.
Como exponho uma Add(int x, int y)
função dentro de uma biblioteca de classes para um aplicativo de console dentro do .Net Core? Vejo System.ServiceModel.Web e, uma vez que se trata de uma plataforma cruzada, tenho que criar um serviço RESTful?
do I have to create a RESTful service?
- AFAIK sim (ou use alguma solução de terceiros que não conheço para .NET Core)Respostas:
O WCF não é compatível com o .NET Core, pois é uma tecnologia específica do Windows e o .NET Core deve ser multiplataforma.
Se você estiver implementando a comunicação entre processos, considere tentar o projeto IpcServiceFramework .
Ele permite criar serviços no estilo WCF como este:
Criar contrato de serviço
public interface IComputingService { float AddFloat(float x, float y); }
Implementar o serviço
class ComputingService : IComputingService { public float AddFloat(float x, float y) { return x + y; } }
Hospedar o serviço no aplicativo de console
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>(); } }
Chame o serviço do processo do 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));
fonte
Você pode usar o gRPC para hospedar serviços da web dentro do aplicativo .NET core.
Introdução
Exemplo
Código do 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(); } }
Código do 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(); } }
Aulas compartilhadas entre cliente e 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; } }
Descritores de serviço
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)); }
Serializer / Deserializer
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; } }
Resultado
Saída de amostra do cliente
Resultado do servidor de amostra
Referências
Benchmarks
fonte
gRPC
, não compila na cadeia de ferramentas nativas .net no VS 2019 (16.0.2) e, portanto, não funcionará com UWP.Parece que haverá um projeto CoreWCF mantido pela .NET Foundation com suporte da Microsoft.
Mais detalhes em Welcoming Core WCF to the .NET Foundation
Inicialmente, apenas transporte netTcp e http serão implementados.
fonte
O WCF faz muitas coisas; é uma maneira fácil de realizar chamadas de procedimento remoto entre dois aplicativos (processos) em uma máquina, usando canais nomeados; pode ser um canal de comunicação cliente-servidor interno de alto volume entre componentes .NET, usando serialização binária sobre TCPIP; ou pode fornecer uma API de tecnologia cruzada padronizada, por exemplo, via SOAP. Ele ainda tem suporte para coisas como mensagens assíncronas, via MSMQ.
Para o .NET Core, existem diferentes substituições com base na finalidade.
Para API de plataforma cruzada, você deve substituir isso por um serviço REST usando ASP.NET.
Para conexões entre processos, ou conexão cliente-servidor, gRPC seria bom, com uma excelente resposta dada por @Gopi.
Portanto, a resposta para "O que substitui o WCF" depende de para que você o está usando.
fonte
Há um repositório da comunidade https://github.com/CoreWCF/CoreWCF que implementa algumas partes do WCF. Você pode usá-lo para oferecer suporte a alguns serviços WCF simples. No entanto, nem todos os recursos são suportados.
fonte
Portanto, de acordo com minha pesquisa, a melhor solução não possui as classes de proxy geradas automaticamente. A melhor solução é criar um serviço RESTful e serializar o corpo de resposta em objetos de modelo. Onde os modelos são os objetos de modelo usuais encontrados no padrão de projeto MVC.
Obrigado por suas respostas
fonte
Você também pode hospedar a API da Web ASP.NET Core.
<!-- SelfHosted.csproj --> <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>netcoreapp3.1</TargetFramework> </PropertyGroup> <ItemGroup> <!-- see: https://docs.microsoft.com/en-us/aspnet/core/migration/22-to-30?view=aspnetcore-3.1&tabs=visual-studio#framework-reference --> <FrameworkReference Include="Microsoft.AspNetCore.App" /> <PackageReference Include="Microsoft.Extensions.Hosting" Version="3.1.0" /> </ItemGroup> </Project>
// Program.cs using System.IO; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Hosting; namespace SelfHosted { class Program { static void Main(string[] args) { CreateHostBuilder(args).Build().Run(); } public static IHostBuilder CreateHostBuilder(string[] args) { // see: https://docs.microsoft.com/en-us/aspnet/core/fundamentals/host/generic-host?view=aspnetcore-3.1 return Host.CreateDefaultBuilder(args) .ConfigureHostConfiguration(configHost => { configHost.SetBasePath(Directory.GetCurrentDirectory()); configHost.AddJsonFile("appsettings.json", optional: true); configHost.AddEnvironmentVariables(prefix: "SelfHosted_"); configHost.AddCommandLine(args); }) .ConfigureWebHostDefaults(webBuilder => { webBuilder.CaptureStartupErrors(true); webBuilder.UseStartup<Startup>(); }); } } }
// Startup.cs using System; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; namespace SelfHosted { public class Startup { public Startup(IConfiguration configuration, IWebHostEnvironment env) { Configuration = configuration; } public IConfiguration Configuration { get; } public void ConfigureServices(IServiceCollection services) { // see: https://github.com/aspnet/AspNetCore.Docs/tree/master/aspnetcore/web-api/index/samples/3.x services.AddControllers(); } public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseExceptionHandler("/Error"); app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); } } }
// Controllers\TestController.cs using System.Net.Mime; using Microsoft.AspNetCore.Mvc; namespace SelfHosted.Controllers { [ApiController] [Produces(MediaTypeNames.Application.Json)] [Route("[controller]")] public class HelloController : SelfHostedControllerBase { [HttpGet] public ActionResult<string> HelloWorld() => "Hello World!"; [HttpGet("{name}")] public ActionResult<string> HelloName(string name) => $"Hello {name}!"; } }
fonte
Há uma porta .NET Core disponível: https://github.com/dotnet/wcf Ela ainda está em visualização, mas eles estão desenvolvendo-a ativamente.
fonte
Como hoje, todos os selfhost disponíveis WCFCore não são tão fáceis de instalar e usar.
O melhor para HostedService serão as alternativas como gRPC mostrou na resposta anterior e observe que em 1 ano pode mudar muitas coisas se o WCF é suportado no Core apenas como um cliente que funciona bem.
fonte