Je suis habitué à créer une application console .Net Framework et à exposer une fonction Add(int x, int y)
via un service WCF à partir de zéro avec la bibliothèque de classes (.Net Framework). J'utilise ensuite l'application console pour appeler par proxy cette fonction sur le serveur.
Cependant, si j'utilise Console App (.Net Core) et une bibliothèque de classes (.Net Core), System.ServiceModel n'est pas disponible. J'ai fait quelques recherches sur Google mais je n'ai pas trouvé ce qui "remplace" la WCF dans ce cas.
Comment exposer une fonction Add(int x, int y)
dans une bibliothèque de classes à une application console, le tout dans .Net Core? Je vois System.ServiceModel.Web, et puisque ceci essaie d'être multi-plateforme, dois-je créer un service RESTful?
WCF n'est pas pris en charge dans .NET Core, car il s'agit d'une technologie spécifique à Windows, alors que .NET Core est censé être multi-plateforme. Si vous implémentez une communication inter-processus, envisagez d’essayer ce projet . Il permet de créer des services dans le style WCF:
Étape 1 - Créer un contrat de service
public interface IComputingService
{
float AddFloat(float x, float y);
}
Étape 2: implémenter le service
class ComputingService : IComputingService
{
public float AddFloat(float x, float y)
{
return x + y;
}
}
Étape 3 - Hébergez le service dans l'application console
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>();
}
}
Étape 4 - Appeler le service depuis le processus client
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));
Vous pouvez utiliser gRPC pour l'hébergement de services Web dans l'application principale .NET.
Introduction
Exemple
Code serveur
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();
}
}
Code client
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();
}
}
Classes partagées entre le client et le serveur
[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; }
}
Descripteurs de service
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));
}
Sérialiseur/Désérialiseur
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;
}
}
Sortie
Références
Points de repère
Il semble qu'il y aura un projet Core WCF maintenu par .NET Foundation avec le support de Microsoft. Plus de détails ici: https://www.dotnetfoundation.org/blog/2019/06/07/welcoming-core-wcf-to-the-net-foundation
Initialement, seuls les transports netTcp et http seront implémentés.
Donc, d'après mes recherches, la meilleure solution n'a pas les classes de proxy générées automatiquement. La meilleure solution consiste à créer un service RESTful et à sérialiser le corps de la réponse en objets de modèle. Où les modèles sont les objets de modèle habituels trouvés dans le modèle de conception MVC.
Merci pour vos réponses
Il existe un port .NET Core disponible: https://github.com/dotnet/wcf Il est toujours en aperçu, mais ils le développent activement.