Skip to content

Commit f98a835

Browse files
author
Meir Kriheli
committed
do not take methods of inherited interface which is not marked as service contract.
this will reflect the GRPC behavior which such interface's methods.
1 parent acd8a2f commit f98a835

File tree

2 files changed

+32
-6
lines changed

2 files changed

+32
-6
lines changed

src/protobuf-net.Grpc.Reflection/SchemaGenerator.cs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ public string GetSchema(Type contractType)
4949
Name = name
5050
};
5151

52-
var ops = GetMethodsRecursively(contractType);
52+
var ops = GetMethodsRecursively(binder, contractType);
5353
foreach (var method in ops)
5454
{
5555
if (method.DeclaringType == typeof(object))
@@ -103,11 +103,14 @@ static Type ApplySubstitutes(Type type)
103103
}
104104
}
105105

106-
private static MethodInfo[] GetMethodsRecursively(Type contractType)
106+
private static MethodInfo[] GetMethodsRecursively(ServiceBinder serviceBinder, Type contractType)
107107
{
108108
var methods = contractType.GetMethods(BindingFlags.Public | BindingFlags.Instance);
109-
var baseInterfaces = contractType.GetInterfaces();
110-
var inheritedMethods = baseInterfaces.SelectMany(iface => GetMethodsRecursively(iface)).ToArray();
109+
var baseContractInterfaces =
110+
contractType.GetInterfaces()
111+
.Where(cType => serviceBinder.IsServiceContract(cType, out _)); // only the ones marked as contract type
112+
113+
var inheritedMethods = baseContractInterfaces.SelectMany(cType => GetMethodsRecursively(serviceBinder, cType)).ToArray();
111114
if (inheritedMethods.Any())
112115
return inheritedMethods.Concat(methods).ToArray();
113116

tests/protobuf-net.Grpc.Reflection.Test/SchemaGeneration.cs

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,14 +110,29 @@ public interface IMyService
110110
void SyncEmpty();
111111
}
112112

113+
/// <summary>
114+
/// An interface which is not marked with [Service] attribute.
115+
/// Its methods are not expected to participate in reflection at all.
116+
/// </summary>
117+
public interface INotAService
118+
{
119+
ValueTask<MyResponse> NotAServiceUnary(MyRequest request, CallContext callContext = default);
120+
ValueTask<MyResponse> NotAServiceClientStreaming(IAsyncEnumerable<MyRequest> request, CallContext callContext = default);
121+
IAsyncEnumerable<MyResponse> NotAServiceServerStreaming(MyRequest request, CallContext callContext = default);
122+
IAsyncEnumerable<MyResponse> NotAServiceFullDuplex(IAsyncEnumerable<MyRequest> request, CallContext callContext = default);
123+
124+
ValueTask NotAServiceAsyncEmpty();
125+
void NotAServiceSyncEmpty();
126+
}
127+
113128
[Service]
114-
public interface ISomeGenericService<TGenericRequest, TGenericResult>
129+
public interface ISomeGenericService<in TGenericRequest, TGenericResult>
115130
{
116131
ValueTask<TGenericResult> GenericUnary(TGenericRequest request, CallContext callContext = default);
117132
}
118133

119134
[Service]
120-
public interface IMyInheritedService : IMyService, ISomeGenericService<MyRequest, MyResponse>
135+
public interface IMyInheritedService : IMyService, ISomeGenericService<MyRequest, MyResponse>, INotAService
121136
{
122137
ValueTask<MyResponse> InheritedUnary(MyRequest request, CallContext callContext = default);
123138
ValueTask<MyResponse> InheritedClientStreaming(IAsyncEnumerable<MyRequest> request, CallContext callContext = default);
@@ -212,5 +227,13 @@ service ConferencesService {
212227
}
213228
", proto, ignoreLineEndingDifferences: true);
214229
}
230+
231+
[Fact]
232+
public void WhenInterfaceIsNotServiceContract_Throw()
233+
{
234+
var generator = new SchemaGenerator();
235+
Action activation = () => generator.GetSchema<INotAService>();
236+
Assert.Throws<ArgumentException>(activation.Invoke);
237+
}
215238
}
216239
}

0 commit comments

Comments
 (0)