Jestem przyzwyczajony do tworzenia aplikacji konsolowej .Net Framework i eksponowania Add(int x, int y)
funkcji za pośrednictwem usługi WCF od podstaw za pomocą Class Library (.Net Framework). Następnie używam aplikacji konsoli do wywołania tej funkcji na serwerze przez proxy.
Jeśli jednak używam aplikacji konsoli (.Net Core) i biblioteki klas (.Net Core), System.ServiceModel nie jest dostępny. Zrobiłem kilka Google, ale nie wiem, co „zastępuje” WCF w tym przypadku.
Jak udostępnić Add(int x, int y)
funkcję w bibliotece klas aplikacji konsolowej w ramach .Net Core? Widzę System.ServiceModel.Web, a ponieważ próbuję działać na wielu platformach, czy muszę utworzyć usługę RESTful?
do I have to create a RESTful service?
- AFAIK tak (lub użyj rozwiązania innej firmy, którego nie znam dla .NET Core)Odpowiedzi:
Usługa WCF nie jest obsługiwana w programie .NET Core, ponieważ jest to technologia specyficzna dla systemu Windows, a platforma .NET Core powinna być wieloplatformowa.
Jeśli wdrażasz komunikację między procesami, rozważ wypróbowanie projektu IpcServiceFramework .
Umożliwia tworzenie usług w stylu WCF w następujący sposób:
Utwórz umowę serwisową
public interface IComputingService { float AddFloat(float x, float y); }
Wdrażaj usługę
class ComputingService : IComputingService { public float AddFloat(float x, float y) { return x + y; } }
Hostuj usługę w aplikacji konsolowej
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>(); } }
Wywołaj usługę z procesu klienta
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));
źródło
Możesz użyć gRPC do hostowania usług internetowych w aplikacji .NET core.
Wprowadzenie
Przykład
Kod serwera
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(); } }
Kod klienta
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(); } }
Klasy współdzielone między klientem a serwerem
[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; } }
Deskryptory usług
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)); }
Serializator / Deserializator
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; } }
Wynik
Przykładowe dane wyjściowe klienta
Przykładowe dane wyjściowe serwera
Bibliografia
Benchmarki
źródło
gRPC
nie kompiluje się z natywnym łańcuchem narzędzi .net w VS 2019 (16.0.2) i dlatego nie będzie działać z UWP.Wygląda na to, że powstanie projekt CoreWCF obsługiwany przez .NET Foundation przy wsparciu Microsoft.
Więcej informacji na temat powitania Core WCF w .NET Foundation
Początkowo zaimplementowany zostanie tylko transport netTcp i http.
źródło
WCF robi wiele rzeczy; jest to łatwy sposób na zdalne wywołanie procedur między dwiema aplikacjami (procesami) na jednym komputerze przy użyciu nazwanych potoków; może to być wewnętrzny kanał komunikacyjny klient-serwer o dużej objętości między komponentami .NET, wykorzystujący serializację binarną przez TCPIP; lub może zapewnić znormalizowany interfejs API obejmujący różne technologie, np. za pośrednictwem protokołu SOAP. Obsługuje nawet takie rzeczy, jak asynchroniczne przesyłanie wiadomości za pośrednictwem usługi MSMQ.
W przypadku platformy .NET Core istnieją różne zamienniki w zależności od celu.
W przypadku interfejsu API dla wielu platform należy go zastąpić usługą REST przy użyciu programu ASP.NET.
W przypadku połączeń między procesami lub połączeń klient-serwer gRPC byłby dobry, z doskonałą odpowiedzią udzieloną przez @Gopi.
Tak więc odpowiedź na pytanie „Co zastępuje WCF” zależy od tego, do czego go używasz.
źródło
Istnieje repozytorium społeczności https://github.com/CoreWCF/CoreWCF, które implementuje niektóre części WCF. Możesz go użyć do obsługi niektórych prostych usług WCF. Jednak nie wszystkie funkcje są obsługiwane.
źródło
Z moich badań wynika, że najlepsze rozwiązanie nie ma automatycznie generowanych klas proxy. Najlepszym rozwiązaniem jest utworzenie usługi RESTful i serializacja treści odpowiedzi do obiektów modelu. Gdzie modele są zwykłymi obiektami modelu znalezionymi we wzorcu projektowym MVC.
Dziękuję za odpowiedzi
źródło
Możesz również samodzielnie hostować ASP.NET Core Web API.
<!-- 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}!"; } }
źródło
Dostępny jest port .NET Core: https://github.com/dotnet/wcf Nadal jest w wersji zapoznawczej, ale aktywnie go rozwijają.
źródło
Ponieważ obecnie wszystkie dostępne usługi Selfhost WCFCore nie są tak łatwe w instalacji i obsłudze.
Najlepszym rozwiązaniem dla HostedService będą alternatywy, jak pokazał gRPC w poprzedniej odpowiedzi i zauważ, że w ciągu 1 roku może zmienić wiele rzeczy, na pewno WCF jest obsługiwany w Core tylko jako klient, który działa dobrze.
źródło