我习惯于创建一个.Net Framework控制台应用程序,并通过WCF服务从头开始使用类库(.Net Framework)公开Add(int x, int y)
函数。然后我使用控制台应用程序在服务器内代理调用此函数。
但是,如果我使用Console App(.Net Core)和类库(.Net Core),则System.ServiceModel不可用。我做了一些谷歌搜索,但我还没有弄清楚"取代"在这种情况下的WCF。
如何在类库中将Add(int x, int y)
函数公开到.Net Core中的控制台应用程序?我看到System.ServiceModel.Web,因为这是尝试跨平台,我是否必须创建一个RESTful服务?
答案 0 :(得分:19)
您可以使用gRPC在.NET核心应用程序中托管Web服务。
简介
示例
服务器代码
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 :(得分:16)
.NET Core不支持WCF,因为它是Windows特定技术,而.NET Core应该是跨平台的。 如果要实现进程间通信,请考虑尝试this project。 它允许以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));
答案 2 :(得分:5)
似乎,.NET Foundation将在Microsoft支持下维护一个Core WCF项目。此处有更多详细信息:https://www.dotnetfoundation.org/blog/2019/06/07/welcoming-core-wcf-to-the-net-foundation
最初仅将实现netTcp和http传输。
答案 3 :(得分:4)
因此,根据我的研究,最佳解决方案没有自动生成的代理类。这个最佳解决方案是创建RESTful服务并将响应主体序列化为模型对象。模型是MVC设计模式中常见的模型对象。
感谢您的回复
答案 4 :(得分:3)
What's new in .NET 5 / Windows Communication Foundation
Windows Communication Foundation (WCF) 的原始实现仅在 Windows 上受支持。但是,.NET Foundation 提供了一个客户端端口。它是完全开源的、跨平台的,并由 Microsoft 提供支持。
社区维护补充上述客户端库的服务器组件。 GitHub 存储库可以在 CoreWCF 中找到。 Microsoft 不正式支持服务器组件。对于 WCF 的替代方案,请考虑 gRPC。
答案 5 :(得分:1)
有一个实现WCF某些部分的社区仓库https://github.com/CoreWCF/CoreWCF。您可以使用它来支持一些简单的WCF服务。但是,并非所有功能都受支持。
答案 6 :(得分:0)
有一个可用的.NET Core端口:https://github.com/dotnet/wcf 它仍在预览中,但是他们正在积极开发它。
答案 7 :(得分:0)
您还可以自托管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}!";
}
}
答案 8 :(得分:0)
今天,所有可用的WCFCore自托管主机都不容易安装和使用。
对于HostedService来说,最好的方法是gRPC在上一个答案中显示的替代方法,并请注意,在1年内可以更改许多功能,确保仅在工作正常的客户端上,Core中支持WCF。