Skip to content

Commit 14f4416

Browse files
author
Jacques Kang
committed
re-implement IpcServiceClient using dynamic proxy -> client app do not need to implement any proxy class anymore
1 parent 64344f1 commit 14f4416

File tree

11 files changed

+116
-128
lines changed

11 files changed

+116
-128
lines changed

README.md

Lines changed: 26 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -5,124 +5,74 @@
55
A .NET Core lightweight inter-process communication framework allowing invoking a service via named pipeline (in a similar way as WCF, which is currently unavailable for .NET Core).
66

77
Support using primitive or complexe types in service contract.
8+
89
Support multi-threading on server side with configurable number of threads.
910

1011
[ASP.NET Core Dependency Injection framework](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection) friendly.
1112

1213
## Usage
13-
1. Create an interface as service contract (ideally package in a shared assembly)
14-
2. Implement a client proxy with help of abstract class provided by framework
15-
3. Implement the service and register in IoC container
16-
4. Host the service in an console or web applciation
14+
1. Create an interface as service contract and package it in an assembly to be shared between server and client.
15+
2. Implement the service and host it in an console or web applciation
16+
3. Invoke the service with framework provided proxy client
1717

1818
## Sample:
1919

20-
1. Service contract
20+
- Service contract
2121
```csharp
2222
public interface IComputingService
2323
{
24-
ComplexNumber AddComplexNumber(ComplexNumber x, ComplexNumber y);
2524
float AddFloat(float x, float y);
2625
}
2726
```
2827

29-
2. Client side
28+
- Service implementation
3029

3130
```csharp
32-
// implement proxy
33-
class ComputingServiceClient : IpcServiceClient<IComputingService>, IComputingService
31+
class ComputingService : IComputingService
3432
{
35-
public ComputingServiceClient(string pipeName)
36-
: base(pipeName)
37-
{ }
38-
39-
public ComplexNumber AddComplexNumber(ComplexNumber x, ComplexNumber y)
40-
{
41-
return Invoke<ComplexNumber>(nameof(AddComplexNumber), x, y);
42-
}
43-
4433
public float AddFloat(float x, float y)
4534
{
46-
return Invoke<float>(nameof(AddFloat), x, y);
35+
return x + y;
4736
}
4837
}
4938
```
5039

51-
```csharp
52-
// invoke IPC service
53-
var client = new ComputingServiceClient("pipeName");
54-
float result1 = client.AddFloat(1.23f, 4.56f);
55-
ComplexNumber result2 = client.AddComplexNumber(new ComplexNumber(0.1f, 0.3f), new ComplexNumber(0.2f, 0.6f));
56-
```
57-
58-
3. Server side
40+
- Invoke the service from client process
5941

6042
```csharp
61-
// service implementation
62-
public class ComputingService : IComputingService
63-
{
64-
private readonly ILogger<ComputingService> _logger;
65-
66-
public ComputingService(ILogger<ComputingService> logger) // inject dependencies in constructor
67-
{
68-
_logger = logger;
69-
}
70-
71-
public ComplexNumber AddComplexNumber(ComplexNumber x, ComplexNumber y)
72-
{
73-
_logger.LogInformation($"{nameof(AddComplexNumber)} called.");
74-
return new ComplexNumber(x.A + y.A, x.B + y.B);
75-
}
76-
77-
public float AddFloat(float x, float y)
78-
{
79-
_logger.LogInformation($"{nameof(AddFloat)} called.");
80-
return x + y;
81-
}
82-
}
43+
var proxy = new IpcServiceClient<IComputingService>("pipeName");
44+
float result = await proxy.InvokeAsync(x => x.AddFloat(1.23f, 4.56f));
8345
```
8446

85-
4. Hosting in Console application
47+
- Host the service (Console application)
8648

8749
```csharp
88-
// hosting in Console application
8950
class Program
9051
{
9152
static void Main(string[] args)
9253
{
93-
// build service provider
54+
// configure DI
9455
IServiceCollection services = ConfigureServices(new ServiceCollection());
95-
ServiceProvider serviceProvider = services.BuildServiceProvider();
96-
97-
// configure console logging
98-
serviceProvider.GetRequiredService<ILoggerFactory>()
99-
.AddConsole(LogLevel.Debug);
10056

101-
// TODO start IPC service host
57+
// run IPC service host
10258
IpcServiceHostBuilder
103-
.Buid("pipeName", serviceProvider as IServiceProvider)
104-
.Start();
59+
.Buid("pipeName", services.BuildServiceProvider())
60+
.Run();
10561
}
10662

10763
private static IServiceCollection ConfigureServices(IServiceCollection services)
10864
{
109-
services
110-
.AddLogging();
111-
112-
services
65+
return services
11366
.AddIpc(options =>
11467
{
11568
options.ThreadCount = 4;
11669
})
117-
.AddService<IComputingService, ComputingService>()
118-
;
119-
120-
return services;
70+
.AddService<IComputingService, ComputingService>();
12171
}
12272
}
12373
```
12474

125-
5. Hosting in Web application
75+
- Host the service (Web application)
12676

12777
```csharp
12878
public class Program
@@ -131,6 +81,7 @@ Support multi-threading on server side with configurable number of threads.
13181
{
13282
IWebHost webHost = BuildWebHost(args);
13383

84+
// run the IPC service host in a separated thread because it's blocking
13485
ThreadPool.QueueUserWorkItem(StartIpcService,
13586
webHost.Services.CreateScope().ServiceProvider);
13687

@@ -142,7 +93,7 @@ Support multi-threading on server side with configurable number of threads.
14293
var serviceProvider = state as IServiceProvider;
14394
IpcServiceHostBuilder
14495
.Buid("pipeName", serviceProvider as IServiceProvider)
145-
.Start();
96+
.Run();
14697
}
14798

14899
public static IWebHost BuildWebHost(string[] args) =>
@@ -159,18 +110,16 @@ Support multi-threading on server side with configurable number of threads.
159110
public void ConfigureServices(IServiceCollection services)
160111
{
161112
services
162-
.AddIpc()
113+
.AddIpc(options =>
114+
{
115+
options.ThreadCount = 4;
116+
})
163117
.AddService<IComputingService, ComputingService>()
164118
;
165119
}
166120

167121
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
168122
{
169-
if (env.IsDevelopment())
170-
{
171-
app.UseDeveloperExceptionPage();
172-
}
173-
174123
app.Run(async (context) =>
175124
{
176125
await context.Response.WriteAsync("Hello World!");
@@ -179,7 +128,7 @@ Support multi-threading on server side with configurable number of threads.
179128
}
180129
```
181130

182-
I'll publish a NuGet package soon.
131+
I'll publish NuGet packages later.
183132

184133
Any contributions or comments are welcome!
185134

src/IpcServiceSample.ConsoleClient/ComputingServiceClient.cs

Lines changed: 0 additions & 21 deletions
This file was deleted.

src/IpcServiceSample.ConsoleClient/Program.cs

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,36 @@
11
using IpcServiceSample.ServiceContracts;
2+
using JKang.IpcServiceFramework;
23
using System;
4+
using System.Threading.Tasks;
35

46
namespace IpcServiceSample.ConsoleClient
57
{
68
class Program
79
{
810
static void Main(string[] args)
11+
{
12+
MainAsync(args).Wait();
13+
}
14+
15+
private static async Task MainAsync(string[] args)
916
{
1017
try
1118
{
12-
Console.WriteLine("Invoking IpcService...");
13-
var client = new ComputingServiceClient("pipeName");
19+
var client = new IpcServiceClient<IComputingService>("pipeName");
1420

15-
float result1 = client.AddFloat(1.23f, 4.56f);
21+
// test 1: call IPC service method with primitive types
22+
float result1 = await client.InvokeAsync(x => x.AddFloat(1.23f, 4.56f));
1623
Console.WriteLine($"sum of 2 floating number is: {result1}");
1724

18-
client.DoNothing();
19-
ComplexNumber result2 = client.AddComplexNumber(
25+
// test 1: call IPC service method with complex types
26+
ComplexNumber result2 = await client.InvokeAsync(x => x.AddComplexNumber(
2027
new ComplexNumber(0.1f, 0.3f),
21-
new ComplexNumber(0.2f, 0.6f));
28+
new ComplexNumber(0.2f, 0.6f)));
2229
Console.WriteLine($"sum of 2 complexe number is: {result2.A}+{result2.B}i");
30+
31+
// test 3: call IPC service method without parameter or return
32+
await client.InvokeAsync(x => x.DoNothing());
33+
Console.WriteLine($"invoked DoNothing()");
2334
}
2435
catch (Exception ex)
2536
{

src/IpcServiceSample.ConsoleServer/Program.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ static void Main(string[] args)
1717
// TODO start IPC service host
1818
IpcServiceHostBuilder
1919
.Buid("pipeName", serviceProvider as IServiceProvider)
20-
.Start();
20+
.Run();
2121

2222
}
2323

src/IpcServiceSample.ServiceContracts/IComputingService.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,7 @@
33
public interface IComputingService
44
{
55
float AddFloat(float x, float y);
6-
76
ComplexNumber AddComplexNumber(ComplexNumber x, ComplexNumber y);
8-
97
void DoNothing();
108
}
119

src/IpcServiceSample.WebServer/Program.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ private static void StartIpcService(object state)
2424
var serviceProvider = state as IServiceProvider;
2525
IpcServiceHostBuilder
2626
.Buid("pipeName", serviceProvider as IServiceProvider)
27-
.Start();
27+
.Run();
2828
}
2929

3030
public static IWebHost BuildWebHost(string[] args) =>

0 commit comments

Comments
 (0)