.Net Core'da WCF'nin yerini ne alır?


96

Bir .Net Framework konsol uygulaması oluşturmaya ve Add(int x, int y)Sınıf Kitaplığı (.Net Framework) ile bir WCF hizmeti aracılığıyla bir işlevi sıfırdan açığa çıkarmaya alışkınım . Daha sonra bu işlevi sunucu içinde proxy olarak çağırmak için konsol uygulamasını kullanıyorum.

Ancak Konsol Uygulaması (.Net Core) ve Sınıf Kitaplığı (.Net Core) kullanırsam System.ServiceModel kullanılamaz. Biraz Googling yaptım, ancak bu durumda WCF'nin neyin "yerini aldığını" bulamadım.

Add(int x, int y)Bir sınıf kitaplığındaki bir işlevi .Net Core içindeki bir konsol uygulamasına nasıl gösteririm? System.ServiceModel.Web'i görüyorum ve bu çapraz platform olmaya çalıştığı için bir RESTful hizmeti oluşturmam gerekiyor mu?


do I have to create a RESTful service?- AFAIK evet (veya .NET Core için hiç bilmediğim bazı 3. Taraf çözümlerini kullanın)
Christoph Fink

3
WCF, büyük olasılıkla .NET Core'a taşınmayacaktır, çünkü kod tabanının çoğu Windows iç kitaplıklarına bağlıdır. ASP.NET Core kullanabilir misiniz? Orada kolayca çapraz platform olan bir HTTP sunucunuz olacak
Camilo Terevinto

2
WCF istemci tarafı zaten destekleniyor (ne kadarını bilmiyorum), sunucu tarafı çok tartışılan ve oylanan bir özellik isteği.
Henk Holterman

Visual Studio 2017 15.5 ve sonraki sürümlerin .NET Core istemci proxy sınıfları oluşturmayı desteklediği görülmektedir . Ayrıca desteklenen özelliklerin bir listesi de vardır .
jamiebarrow

5

Yanıtlar:


35

WCF, Windows'a özgü bir teknoloji olduğu ve .NET Core'un çapraz platform olması gerektiği için .NET Core'da desteklenmez.

İşlemler arası iletişim uyguluyorsanız , IpcServiceFramework projesini denemeyi düşünün .

WCF stilinde şu şekilde hizmet oluşturmaya izin verir:

  1. Hizmet sözleşmesi oluşturun

    public interface IComputingService
    {
        float AddFloat(float x, float y);
    }
    
  2. Hizmeti uygulayın

    class ComputingService : IComputingService
    {
        public float AddFloat(float x, float y)
        {
            return x + y;
        }
    }
    
  3. Hizmeti Konsol uygulamasında barındırın

    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. İstemci işleminden hizmeti çağırın

    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
Güzel! .Net core system.io.pipelines blogs.msdn.microsoft.com/dotnet/2018/07/09/…
Sigex

Pardon, burada önemli bir şeyi mi kaçırıyorum? Boruların yalnızca aynı ana bilgisayar iletişimi için olması gerekmiyor mu?
user1034912

2
Evet, kaçırdığınız şey, bu kısaca, WCF gibi IpcServiceFramework'ün farklı mesajlaşma teknolojileri arasında sorunsuz bir şekilde geçiş yapmanıza izin verdiğini göstermesidir.
Chris F Carroll

4
WCF, özetlediği bazı protokollerde pencerelere özgü olarak kabul edilebilir, ancak SOAP hizmetleri değildir. .Net çekirdeğinde bir SOAP web servisi nasıl oluşturulur?
Jeremy

3
Not: Bu projenin yazarı şu yorumu yazdı: "Arkadaşlar, birkaç aydır bu projeyi sürdürmek için kişisel nedenim yok. Ortalama .NET Core 3.0 gRPC özelliği ile piyasaya sürüldü." ( github.com/jacqueskang/IpcServiceFramework/issues/… ). GRPC için ikinci yanıta bakın.
gerard

64

GRPC'yi .NET çekirdek uygulaması içindeki web hizmetlerini barındırmak için kullanabilirsiniz.

görüntü açıklamasını buraya girin

Giriş

  1. gRPC, başlangıçta Google tarafından geliştirilen yüksek performanslı, açık kaynaklı bir RPC çerçevesidir.
  2. Çerçeve, uzak prosedür çağrılarının bir istemci-sunucu modeline dayanmaktadır. Bir istemci uygulaması, yerel bir nesne gibi, bir sunucu uygulamasındaki yöntemleri doğrudan çağırabilir.

Misal

Sunucu Kodu

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

Müşteri kodu

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

İstemci ve Sunucu arasında Paylaşılan Sınıflar

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

Hizmet tanımlayıcıları

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

Serileştirici / Seri Çözücü

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

Çıktı

Örnek müşteri çıktısı

Örnek Sunucu çıktısı

Referanslar

  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

Kıyaslamalar

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

7
Mart 2019 itibariyle, bu cevap daha alakalı. Bkz github.com/grpc/grpc-dotnet (ve ASP.NET Çekirdek .NET Çekirdek 3.0 günceller ).
resnyanskiy

1
Bunun en yakın cevap olduğunu düşünüyorum ama yine de maalesef herhangi bir davranış veya kısıtlayıcı destek sağlamıyor.
joe

4
Ayrıca şu an itibariyle gRPCVS 2019'da (16.0.2) .net yerel araç zincirine karşı derlenmediğini ve bu nedenle UWP ile çalışmayacağını unutmayın.
Samuel

2
Adlandırılmış boru desteği arıyorsanız, bir gRPC aktarımı yazdım: github.com/cyanfish/grpc-dotnet-namedpipes
Cyanfish

1
(2020-04-06 itibariyle) grpc-dotnet'in ARM için paketleri olmadığını unutmayın.
GafferMan2112

23

NET Foundation tarafından Microsoft desteği ile sürdürülen bir CoreWCF projesi olacak gibi görünüyor .

Çekirdek WCF'yi .NET Temelinde Karşılama bölümünde daha fazla ayrıntı

Başlangıçta yalnızca netTcp ve http aktarımı uygulanacaktır.


Bu yanıltıcı bir cevaptır. Microsoft yalnızca wcf istemcisini taşıdı. Wcf ana bilgisayarı veya hizmet ana bilgisayarı kullanılamıyor ve buna niyetleri yok. Bunu zor yoldan öğrendim. gRPC gitmenin yoludur
user1034912

@ user1034912 doğru değilsiniz. CoreWCF, .NET çekirdeğine bağlanan hafif bir WCF sunucusudur. Sınırlamaları vardır, ancak bazı durumlarda iyi bir seçimdir.
Erişim

Evet, yalnızca Tüketici İstemciyseniz, hiçbir hizmet ana makinesi uygulaması yoktur
user1034912

@ user1034912 Hayır, sunucu tarafı mevcut. github.com/CoreWCF/CoreWCF/blob/master/src/Samples/…
Erişim Reddedildi


9

WCF birçok şey yapar; bu, adlandırılmış yöneltmeler kullanarak bir makinedeki iki uygulama (işlem) arasında uzaktan yordam çağrıları yapmanın kolay bir yoludur; TCPIP üzerinden ikili serileştirmeyi kullanarak .NET bileşenleri arasında yüksek hacimli dahili bir istemci-sunucu iletişim kanalı olabilir; veya örneğin SOAP aracılığıyla standartlaştırılmış bir çapraz teknoloji API'si sağlayabilir. MSMQ aracılığıyla eşzamansız mesajlaşma gibi şeyleri bile destekliyor.

.NET Core için, amaca bağlı olarak farklı değiştirmeler vardır.

Platformlar arası API için, bunu ASP.NET kullanarak bir REST hizmetiyle değiştirirsiniz.

İşlemler arası bağlantılar veya istemci-sunucu bağlantısı için gRPC, @Gopi tarafından verilen mükemmel bir cevapla iyi olur.

Bu nedenle, "WCF'nin yerini ne alır" sorusunun yanıtı, onu ne için kullandığınıza bağlıdır.



4

Bu yüzden araştırmamdan en iyi çözüm otomatik olarak oluşturulan proxy sınıflarına sahip değil. Bu en iyi çözüm, bir RESTful hizmeti oluşturmak ve yanıt gövdesini model nesnelerine serileştirmektir. Modellerin, MVC tasarım modelinde bulunan olağan model nesneler olduğu yer.

Cevaplarınız için teşekkür ederim



Evet, istediğim otomatik olarak oluşturulan vekil sınıflarıydı. Bu işlevsellik için RESTful hizmetleri / RPC kullanıyorum
Sigex

Bu depo yalnızca istemci kitaplıkları içindir
orellabac

Restful, çift yönlü iletişimi desteklemez
user1034912

1

Ayrıca ASP.NET Core Web API'sini kendiniz barındırabilirsiniz.

<!-- 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 çekirdek web api, wcf'nin yaptığı gibi tek bir bağlantı noktasında çift yönlü iletişimi desteklemez.
user1034912

0

Kullanılabilir bir .NET Core bağlantı noktası var: https://github.com/dotnet/wcf Hala önizleme aşamasındadır, ancak aktif olarak geliştirmektedirler.


14
Bu bağlantı noktasının Core'dan WCF'ye iletişim için olduğuna inanıyorum, ancak Core'da WCF yazmak için değil.
hal9000

7
Bağlantılı github deposu açıkça şunu söylüyor: "Bu depo, .NET Core üzerine kurulu uygulamaların WCF hizmetleriyle iletişim kurmasını sağlayan istemci odaklı WCF kitaplıklarını içerir."
Bahaa

0

Bugün olduğu gibi, Mevcut tüm WCFCore selfhost'ların kurulumu ve kullanımı o kadar kolay değildir.
HostedService için en iyisi, önceki yanıtta gRPC'nin gösterdiği gibi alternatifler olacaktır ve 1 yıl içinde WCF'nin Core'da yalnızca iyi çalışan bir istemci olarak desteklendiğinden emin olan birçok şeyi değiştirebileceğini fark edeceksiniz.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.