You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/gettingstarted.md
+58-4Lines changed: 58 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -74,9 +74,63 @@ public class MultiplyResult
74
74
Object models can be arbitrarily deep and complex (including lists, arrays, etc), but should be trees (not graphs).
75
75
76
76
77
-
Service contracts are interfaces marked with `[ServiceContract]`. You can optionally specify the gRPC service name, otherwise it'll use
78
-
reasonable convention-based defaults. Individual RPC calls are methods, which can optionally be marked with `[OperationContract]` to control
79
-
the name.
77
+
Service contracts are interfaces marked with `[ServiceContract]` (from `System.ServiceModel`) or `[Service]` (protobuf-net.Grpc inbuilt). You can optionally specify the gRPC service name, otherwise it'll use
78
+
reasonable convention-based defaults. Individual RPC calls are methods, which can optionally be marked with `[OperationContract]` (from `System.ServiceModel`) or `[Operation]` (protobuf-net.Grpc inbuilt) to control
79
+
the name. There is also `[SubService]`, which is used as below.
80
+
81
+
### Interface inheritance works, with 2 possible scenarios:
82
+
83
+
1. Inherited interfaces as distinct routable services
84
+
85
+
Consider:
86
+
87
+
```c#
88
+
[Service("foo")]
89
+
interfaceIFoo : IBar
90
+
{
91
+
TaskA();
92
+
}
93
+
[Service("bar")]
94
+
interfaceIBar
95
+
{
96
+
TaskB();
97
+
}
98
+
```
99
+
100
+
Here, the bindings are `/foo/A` and `/bar/B`. A client can be constructed for `IBar` by itself, since `IBar` is routable (via `/bar/`). If there was an additional service that *also* inherited `IBar`, they
101
+
could not be used independently, since both uses would want to route via `/bar/.
102
+
103
+
2. Inherited interfaces as composition
104
+
105
+
Consider:
106
+
107
+
```c#
108
+
[Service("foo")]
109
+
interfaceIFoo : IBar
110
+
{
111
+
TaskA();
112
+
}
113
+
[SubService]
114
+
interfaceIBar
115
+
{
116
+
TaskB();
117
+
}
118
+
```
119
+
120
+
Here, the bindings are `/foo/A`, `/foo/B`. The methods from `IBar` are lifted upwards and form part of the `IFoo` service. As a consequence, a client **cannot** be constructed for `IBar` in isolation, as
121
+
`IBar` is not routable without knowing the top-level service to use. The upside of this, however, is that we can add additional services with the same common API, and route them independently. For example, we can add:
122
+
123
+
```c#
124
+
[Service("blap")]
125
+
interfaceIBlap : IBar
126
+
{
127
+
TaskC();
128
+
}
129
+
```
130
+
131
+
This adds the bindings `/blap/C` and `/blap/B`, so now we have two completely independent routable implementations of `B()`. This is especially useful for generic scenarios, common repositories, etc.
132
+
133
+
### Call types
80
134
81
135
In gRPC, there are 4 types of call available:
82
136
@@ -88,7 +142,7 @@ In gRPC, there are 4 types of call available:
88
142
Let's start with unary; a simple example there might be:
89
143
90
144
```c#
91
-
[ServiceContract(Name="Hyper.Calculator")]
145
+
[ServiceContract(Name="Hyper.Calculator")]// or [Service("Hyper.Calculator")]
0 commit comments