.Net CoreのWCFに代わるものは何ですか?


100

私は、.Net Frameworkコンソールアプリケーションを作成し、Add(int x, int y)クラスライブラリ(.Net Framework)を使用してWCFサービスを介して関数を最初から公開することに慣れています。次に、コンソールアプリケーションを使用して、サーバー内でこの関数をプロキシ呼び出しします。

ただし、コンソールアプリ(.Net Core)とクラスライブラリ(.Net Core)を使用している場合、System.ServiceModelは使用できません。グーグルを実行しましたが、この場合にWCFを「置き換える」ものがわかりません。

Add(int x, int y)クラスライブラリ内の関数をすべて.NetCore内のコンソールアプリケーションに公開するにはどうすればよいですか?System.ServiceModel.Webが表示されますが、これはクロスプラットフォームを目指しているため、RESTfulサービスを作成する必要がありますか?


do I have to create a RESTful service?--AFAIKはい(または.NET Coreでは知らないサードパーティのソリューションを使用します)
Christoph Fink

3
ほとんどのコードベースはWindows内部ライブラリに依存しているため、WCFは.NETCoreに移植されない可能性があります。ASP.NET Coreを使用できますか?そこには、簡単にクロスプラットフォーム化できるHTTPサーバーがあります
Camilo Terevinto 2018年

2
WCFクライアント側はすでにサポートされており(どれだけかはわかりません)、サーバー側は熱く議論され、投票された機能要求です。
ヘンクホルターマン2018年

Visual Studio 2017 15.5以降では、.NETCoreクライアントプロキシクラスの生成がサポートされているようです。サポートされている機能のリストもあります
jamiebarrow 2018年

5
要するに:CoreWCF
OgnyanDimitrov19年

回答:


35

WCFはWindows固有のテクノロジであり、.NET Coreはクロスプラットフォームであると想定されているため、.NETCoreではサポートされていません。

プロセス間通信を実装している場合は、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));
    

3
いいね!.Netコアシステムを利用するには、更新する価値があるかもしれません 。io.pipelinesblogs.msdn.microsoft.com
dotnet / 2018/07/09 /

申し訳ありませんが、ここで重要な何かが欠けていますか?パイプは同じホスト通信専用ではありませんか?
user1034912 2018年

2
はい、あなたが見逃しているのは、これは、WCFのようなIpcServiceFrameworkを使用すると、さまざまなメッセージングテクノロジ間でシームレスに切り替えることができることを簡単に示していることです。
クリスFキャロル

4
WCFは、抽象化するプロトコルの一部でWindows固有と見なされる場合がありますが、SOAPサービスはそうではありません。.netコアでSOAPWebサービスを作成するにはどうすればよいですか?
ジェレミー

3
注:このプロジェクトの作者は次のコメントを書いています:「みんな、個人的な理由で、私は数ヶ月以来このプロジェクトを維持する時間がありません。その間に.NET Core3.0はgRPC機能でリリースされます。」(github.com/jacqueskang/IpcServiceFramework/issues/…)。gRPCの2番目の回答を参照してください。
ジェラルド・

67

gRPCを使用して、.NETコアアプリケーション内でWebサービスをホストできます。

ここに画像の説明を入力してください

前書き

  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

7
2019年3月の時点で、この回答はより適切です。github.com/grpc/grpc-dotnet(および.NET Core3.0のASP.NETCoreアップデート)を参照してください。
resnyanskiy

1
これが最も近い答えだと思いますが、それでも悲しいことに、動作やスロットルのサポートは提供されていません。
ジョー

4
また、現時点でgRPCは、VS 2019(16.0.2)の.netネイティブツールチェーンに対してコンパイルされないため、UWPでは機能しないことにも注意してください。
サミュエル

2
名前付きパイプのサポートを探しているなら、私はgRPC輸送を書いた:github.com/cyanfish/grpc-dotnet-namedpipes
Cyanfish

1
(2020-04-06現在)grpc-dotnetにはARM用のパッケージがないことに注意してください。
GafferMan21 1220

23

.NETFoundationがMicrosoftのサポートを受けて維持しているCoreWCFプロジェクトがあるようです。

.NETFoundationへのコアWCFの歓迎の詳細

最初は、netTcpとhttpトランスポートのみが実装されます。


これは誤解を招く答えです。Microsoftはwcfクライアントのみを移植しました。Wcfホストまたはservicehostは使用できず、使用する意図はありません。私はこれを難しい方法で学びました。gRPCが進むべき道
user10349 1220年

@ user1034912あなたは正しくありません。CoreWCFは、.NETCoreに移植された軽量のWCFサーバーです。制限がありますが、場合によっては良い選択です。
アクセスが

はい、消費クライアントの場合のみ、サービスホストの実装はありません
user10349 1220年

@ user1034912いいえ、サーバー側が利用可能です。github.com/CoreWCF/CoreWCF/blob/master/src/Samples/…–
アクセスが拒否されました


9

WCFは多くのことを行います。名前付きパイプを使用して、1台のマシン上の2つのアプリケーション(プロセス)間でリモートプロシージャコールを実行する簡単な方法です。TCPIPを介したバイナリシリアル化を使用した、.NETコンポーネント間の大量の内部クライアントサーバー通信チャネルにすることができます。または、SOAPなどを介して標準化されたクロステクノロジーAPIを提供することもできます。MSMQを介した非同期メッセージングなどもサポートしています。

.NET Coreの場合、目的に基づいてさまざまな代替品があります。

クロスプラットフォームAPIの場合、これをASP.NETを使用するRESTサービスに置き換えます。

プロセス間接続、またはクライアント/サーバー接続の場合、gRPCが適切であり、@ Gopiによって優れた回答が得られます。

したがって、「WCFに代わるもの」に対する答えは、WCFを何に使用しているかによって異なります。


5

WCFの一部を実装するコミュニティリポジトリhttps://github.com/CoreWCF/CoreWCFがあります。これを使用して、いくつかの単純なWCFサービスをサポートできます。ただし、すべての機能がサポートされているわけではありません。


4

したがって、私の調査によると、最適なソリューションには自動生成されたプロキシクラスがありません。この最善の解決策は、RESTfulサービスを作成し、応答本文をモデルオブジェクトにシリアル化することです。モデルは、MVCデザインパターンに見られる通常のモデルオブジェクトです。

ご回答ありがとうございます



ええ、私が欲しかったのは自動生成されたプロキシクラスでした。この機能にRESTfulサービス/ RPCを使用しています
Sigex 2018

このレポは、単にクライアントライブラリのためである
orellabac

1

ASP.NET Core WebAPIをセルフホストすることもできます。

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

AspコアWebAPIは、wcfのように単一ポートでの二重通信をサポートしていません。
user10349 1220年

0

利用可能な.NETCoreポートがあります:https//github.com/dotnet/wcf まだプレビュー中ですが、彼らは積極的に開発しています。


14
このポートはCoreからWCFへの通信用であり、CoreでWCFを書き込むためのものではないと思います。
hal9000 2018

7
リンクされたgithubリポジトリには、「このリポジトリには、.NET Core上に構築されたアプリケーションがWCFサービスと通信できるようにするクライアント指向のWCFライブラリが含まれています。」
Bahaa 2018

0

今日のように、利用可能なすべてのWCFCoreセルフホストはインストールと使用がそれほど簡単ではありません。
HostedServiceに最適なのは、gRPCが前の回答で示した代替手段であり、1年で多くのことが変わる可能性があることに注意してください。WCFは正常に動作するクライアントとしてのみCoreでサポートされます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.