什么可以取代.Net 核心中的 WCF?

我习惯于创建一个。Net Framework 从头开始通过类库(。网络架构)。然后我使用控制台应用在服务器中代理调用这个函数。

但是,如果我使用控制台应用程序(。网络核心)及类库(。网络核心)系统。ServiceModel 不可用。我已经做了一些谷歌,但我还没有找出什么“取代”周转基金在这个例子。

如何将类库中的 Add(int x, int y)函数公开给所有类库中的控制台应用。网络核心?我看到了系统。服务模式。因为这是一个跨平台的尝试,所以我必须创建一个 RESTful 服务吗?

127657 次浏览

因此,根据我的研究,最好的解决方案是不使用自动生成的代理类。最好的解决方案是创建一个 RESTful 服务,并将响应主体序列化为模型对象。其中的模型是 MVC 设计模式中常见的模型对象。

谢谢你的回答

中不支持 WCF。NET 核心,因为它是一个 Windows 特有的技术和。NET 核心应该是跨平台的。

如果你正在实施行程间通讯,可以考虑尝试 IpcServiceFramework项目。

它允许创建 WCF 风格的服务,如下所示:

  1. 创建服务合同

    public interface IComputingService
    {
    float AddFloat(float x, float y);
    }
    
  2. 实现服务

    class ComputingService : IComputingService
    {
    public float AddFloat(float x, float y)
    {
    return x + y;
    }
    }
    
  3. 以控制台应用方式举办服务

    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>();
    }
    }
    
  4. 从客户端进程调用服务

    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));
    

有一个可用的.NET 核心端口: < a href = “ https://github.com/dotnet/wcf”rel = “ nofollow norefrer”> https://github.com/dotnet/wcf 虽然还在预览阶段,但他们正在积极开发。

您可以使用 gRPC 在.NET 核心应用程序中托管 Web 服务。

enter image description here

简介

  1. GRPC 是最初由 Google 开发的高性能开源 RPC 框架。
  2. 该框架基于远程过程调用的客户机-服务器模型。客户端应用程序可以像调用本地对象一样直接调用服务器应用程序上的方法。

例子

服务器代码

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();
}
}

客户端代码

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();
}
}

客户端和服务器之间的共享类

[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; }
}

服务描述符

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));
}

序列化器/反序列化器

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;
}
}

输出

客户端输出示例

示例服务器输出

参考文献

  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

基准

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

看来,将有一个 CoreWCF项目维护的.NET 基金会与微软的支持。

详情请浏览 欢迎.NET 基金会的核心周转基金

最初将只实现 netTcp 和 http 传输。

有一个实现 WCF 某些部分的社区回购 https://github.com/CoreWCF/CoreWCF。您可以使用它来支持一些简单的 WCF 服务。然而,并非所有特性都受支持。

您还可以自主管理 ASP.NET 核心 Web API。

<!-- SelfHosted.csproj -->
<Project Sdk="Microsoft.NET.Sdk">


<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>


<ItemGroup>
<!-- see: https://learn.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://learn.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}!";
}
}

WCF 可以做很多事情; 它是一种使用命名管道在一台机器上的两个应用程序(进程)之间进行远程过程调用的简单方法; 它可以是两者之间的大容量内部客户机-服务器通信通道。NET 组件,通过 TCPIP 使用二进制序列化; 或者它可以提供标准化的跨技术 API,例如通过 SOAP。它甚至支持通过 MSMQ 进行异步消息传递。

对于.NETCore,根据用途有不同的替代品。

对于跨平台 API,您可以使用使用 ASP.NET 的 REST 服务替换它。

对于进程间连接或客户机-服务器连接,gRPC 会很好,@Gopi 给出了一个很好的答案。

因此,“什么替代 WCF”的答案取决于您使用它的目的。

正如今天所有的 WCFCore 自主主机可用不是那么容易安装和使用。
对于 HostedService 来说,最好的选择就是 gRPC 在前面的答案中所展示的替代方案,并且注意到在一年内可以改变很多事情,确保 WCF 只作为一个工作良好的客户端在 Core 中得到支持。

.NET5/Windows 通信基础中的新内容

Windows 通信基础(WCF)的原始实现仅在 Windows 上受支持。但是,有一个客户端端口可从。NET 基金会。它是完全开源的,跨平台的,并得到微软的支持。

社区维护服务器组件,以补充前面提到的客户机库。GitHub 存储库可以在 CoreWCF 中找到。微软官方并不支持服务器组件,如果想要替代 WCF,请考虑 < a href = “ https://Learn.Microsoft.com/en-us/dotnet/core/dotnet-five # windows-communications-foundation”rel = “ norefrer”> gRPC 。

// I found a way to implement WCF client proxy in .Net 6.0 (Core):




//--------------------------------------WCF duplex fix------------------------------
// I found a way to fix my problem.. it took me a week of research
// So here it is:
// How to generate WCF Service (.Net Framework 4.8) proxy in client (.Net 6.0):


// If using a callback I need duplex communication


[ServiceContract(CallbackContract = typeof(IEventsService))]


// Just do as explain here but dont expect it to work for Client .Net 6.0 it will
// only work for client .net Framework 4.8 as Wcf service is .Net Framework 4.8

Https://www.codeproject.com/articles/663333/understanding-events-in-wcf#:~:text=background%20while%20events%20in%20wcf%20are%20nothing%20more,typical%20relationship%20between%20a%20client%20and%20a%20service.

// so here is what I need to do to make it work in .Net 6.0 client:
// Use netHttpBinding for duplex
// Put this on web.config of your Wcf service


<service name="HomeManagerWcfService.HomeManagerService" behaviorConfiguration="HomeManagerServiceBehavior">
<host>
<baseAddresses>
<add baseAddress="http://localhost:53318/HomeManagerService"/>
</baseAddresses>
</host>
    

<endpoint address="" binding="netHttpBinding" contract="HomeManagerWcfService.IHomeManagerService"/>
<!--<endpoint address="" binding="wsDualHttpBinding" contract="HomeManagerWcfService.IHomeManagerService"/>-->
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
    

<behaviors>
<serviceBehaviors>
<!-- HomeManagerService Behavior -->
<behavior name="HomeManagerServiceBehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true "/>
</behavior>
</serviceBehaviors>
</behaviors>


// Generate files for your client proxy on VisualStudio.Tools.Command line.Developer command prompt
// The WCF service must be running


svcutil http://localhost:53318/HomeManagerService.svc


//copy both files generated in your client project.
// if using the VS UI generator (Managed connected service) it won't work, there is a bug in it I guess.


// I also need System.ServiceModel.Http
// & I need System.ServiceModel.Duplex
// in the client
// use NetHttpBinding for duplex communication
// Use IHomeManagerServiceCallback to implement the callback function
// where you want it to run the callback


InstanceContext iCntxt = new InstanceContext(this);// "this" is where i implement the callback for my case
var endpointAddress = new EndpointAddress("http://localhost:53318/HomeManagerService.svc");
var binding = new NetHttpBinding();
var factory = new DuplexChannelFactory<IHomeManagerService>(iCntxt, binding, endpointAddress);
var clientWCF = factory.CreateChannel();
    

EmailMessage emailMessage = new EmailMessage();
emailMessage.Name = "ww23";
emailMessage.Body = "SSWDDW223";
emailMessage.EmailAddress = "EMAIL AD dsf2223";
    

clientWCF.SubscribeCalculatedEvent(); // where we register to the event on the server
clientWCF.AddEmail(emailMessage);   // the callback event call is in this function on the server


//----------------------------------------------------------------------------------


// for IIS
// In order to make sure this mapping appears you need to go to control panel
-> turn windows features on or off
-> .NET Framework 4.8 Advanced Services
-> WCF Services -> HTTP Activation

Https://devblogs.microsoft.com/dotnet/corewcf-v1-released/

2022年4月,WCF 可用于以下.NET 核心版本 .NET Core 3.1 .NET 5及6