Skip to content

Commit b33105e

Browse files
authored
Disallow open generics on activity methods (#354)
Fixes #350
1 parent d505adc commit b33105e

File tree

2 files changed

+37
-0
lines changed

2 files changed

+37
-0
lines changed

src/Temporalio/Activities/ActivityDefinition.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,10 @@ public static ActivityDefinition Create(MethodInfo method, Func<object?[], objec
126126
{
127127
var attr = method.GetCustomAttribute<ActivityAttribute>(false) ??
128128
throw new ArgumentException($"{method} missing Activity attribute");
129+
if (method.ContainsGenericParameters)
130+
{
131+
throw new ArgumentException($"{method} contains generic parameters");
132+
}
129133
var parms = method.GetParameters();
130134
return Create(
131135
NameFromAttributed(method, attr),

tests/Temporalio.Tests/Activities/ActivityDefinitionTests.cs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,23 @@ public async Task CreateAll_ClassOfStaticActivities_CanInvoke()
156156
Assert.Equal(128, await defn.InvokeAsync(new object?[] { 123 }));
157157
}
158158

159+
[Fact]
160+
public void CreateAll_OpenGeneric_Throws()
161+
{
162+
var exc = Assert.ThrowsAny<Exception>(() => ActivityDefinition.CreateAll(
163+
typeof(BadActivityGeneric), new BadActivityGeneric()));
164+
Assert.Contains("contains generic parameters", exc.Message);
165+
}
166+
167+
[Fact]
168+
public async Task CreateAll_ClosedGeneric_CanInvoke()
169+
{
170+
var defn = ActivityDefinition.CreateAll(
171+
typeof(GoodActivityGeneric<string>),
172+
new GoodActivityGeneric<string>("some-val")).Single();
173+
Assert.Equal("some-val", await defn.InvokeAsync(Array.Empty<object?>()));
174+
}
175+
159176
protected static void BadAct1()
160177
{
161178
}
@@ -174,6 +191,22 @@ public static class GoodActivityClassStatic
174191
public static int MyActivity(int param) => param + 5;
175192
}
176193

194+
public class BadActivityGeneric
195+
{
196+
[Activity]
197+
public T BadActAsync<T>() => throw new NotSupportedException();
198+
}
199+
200+
public class GoodActivityGeneric<T>
201+
{
202+
private readonly T result;
203+
204+
public GoodActivityGeneric(T result) => this.result = result;
205+
206+
[Activity]
207+
public T GoodAsyncAsync() => result;
208+
}
209+
177210
public class BadActivityClassNoActivities
178211
{
179212
public int ActivityWithoutAttribute(int param) => param + 5;

0 commit comments

Comments
 (0)