Ich bin es gewohnt, eine .Net Framework-Konsolenanwendung zu erstellen und eine Add(int x, int y)
Funktion über einen WCF-Dienst von Grund auf mit Class Library (.Net Framework) verfügbar zu machen. Ich benutze dann die Konsolenanwendung, um diese Funktion innerhalb des Servers als Proxy aufzurufen.
Wenn ich jedoch die Konsolen-App (.Net Core) und eine Klassenbibliothek (.Net Core) verwende, ist das System.ServiceModel nicht verfügbar. Ich habe ein bisschen gegoogelt, aber ich habe nicht herausgefunden, was WCF in diesem Fall "ersetzt".
Wie mache ich eine Add(int x, int y)
Funktion in einer Klassenbibliothek für eine Konsolenanwendung in .Net Core verfügbar? Ich sehe System.ServiceModel.Web, und da dies versucht, plattformübergreifend zu sein, muss ich einen RESTful-Service erstellen?
do I have to create a RESTful service?
- AFAIK ja (oder verwenden Sie eine Drittanbieterlösung, die ich für .NET Core nicht kennen würde)Antworten:
WCF wird in .NET Core nicht unterstützt, da es sich um eine Windows-spezifische Technologie handelt und .NET Core plattformübergreifend sein soll.
Wenn Sie prozessübergreifende Kommunikation implementieren, versuchen Sie es mit dem IpcServiceFramework- Projekt.
Es ermöglicht das Erstellen von Diensten im WCF-Stil wie folgt:
Servicevertrag anlegen
public interface IComputingService { float AddFloat(float x, float y); }
Implementieren Sie den Service
class ComputingService : IComputingService { public float AddFloat(float x, float y) { return x + y; } }
Hosten Sie den Dienst in der Konsolenanwendung
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>(); } }
Rufen Sie den Service vom Client-Prozess aus auf
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));
quelle
Sie können gRPC zum Hosten von Webdiensten in der .NET-Kernanwendung verwenden.
Einführung
Beispiel
Servercode
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(); } }
Kundencode
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(); } }
Gemeinsame Klassen zwischen Client und Server
[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; } }
Service-Deskriptoren
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; } }
Ausgabe
Beispiel für eine Client-Ausgabe
Beispielserverausgabe
Verweise
Benchmarks
quelle
gRPC
Beachten Sie auch, dass derzeit keine Kompilierung mit der nativen .net-Toolkette in VS 2019 (16.0.2) möglich ist und daher nicht mit UWP funktioniert.Es scheint, dass es ein CoreWCF- Projekt geben wird, das von .NET Foundation mit Microsoft-Unterstützung verwaltet wird.
Weitere Informationen finden Sie unter Begrüßung von Core WCF bei der .NET Foundation
Zunächst werden nur netTcp- und http-Transporte implementiert.
quelle
WCF macht viele Dinge; Es ist eine einfache Möglichkeit, Remoteprozeduraufrufe zwischen zwei Anwendungen (Prozessen) auf einem Computer mithilfe von Named Pipes durchzuführen. Es kann sich um einen internen Client-Server-Kommunikationskanal mit hohem Volumen zwischen .NET-Komponenten handeln, der eine binäre Serialisierung über TCPIP verwendet. oder es kann eine standardisierte technologieübergreifende API bereitstellen, z. B. über SOAP. Es unterstützt sogar asynchrones Messaging über MSMQ.
Für .NET Core gibt es je nach Zweck unterschiedliche Ersetzungen.
Bei einer plattformübergreifenden API würden Sie diese mithilfe von ASP.NET durch einen REST-Service ersetzen.
Für prozessübergreifende Verbindungen oder Client-Server-Verbindungen wäre gRPC gut, mit einer ausgezeichneten Antwort von @Gopi.
Die Antwort auf "Was ersetzt WCF" hängt also davon ab, wofür Sie es verwenden.
quelle
Es gibt ein Community-Repo https://github.com/CoreWCF/CoreWCF , das einige Teile von WCF implementiert. Sie können damit einige einfache WCF-Dienste unterstützen. Es werden jedoch nicht alle Funktionen unterstützt.
quelle
Aus meiner Forschung hat die beste Lösung also nicht die automatisch generierten Proxy-Klassen. Diese beste Lösung besteht darin, einen RESTful-Service zu erstellen und den Antworttext in Modellobjekte zu serialisieren. Wo die Modelle die üblichen Modellobjekte sind, die im MVC-Entwurfsmuster gefunden werden.
Vielen Dank für Ihre Antworten
quelle
Sie können die ASP.NET Core-Web-API auch selbst hosten.
<!-- 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}!"; } }
quelle
Es ist ein .NET Core-Port verfügbar: https://github.com/dotnet/wcf Er befindet sich noch in der Vorschau, wird jedoch aktiv weiterentwickelt.
quelle
Wie heute sind alle verfügbaren WCFCore-Selfhosts nicht so einfach zu installieren und zu verwenden.
Das Beste für HostedService sind die Alternativen, wie gRPC in der vorherigen Antwort gezeigt hat. Beachten Sie, dass sich in einem Jahr viele Dinge ändern können, um sicherzustellen, dass WCF in Core nur als Client unterstützt wird, der einwandfrei funktioniert.
quelle