Skip to content

Commit

Permalink
Disallow open generics on activity methods (temporalio#354)
Browse files Browse the repository at this point in the history
  • Loading branch information
cretz authored Oct 8, 2024
1 parent d505adc commit b33105e
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 0 deletions.
4 changes: 4 additions & 0 deletions src/Temporalio/Activities/ActivityDefinition.cs
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,10 @@ public static ActivityDefinition Create(MethodInfo method, Func<object?[], objec
{
var attr = method.GetCustomAttribute<ActivityAttribute>(false) ??
throw new ArgumentException($"{method} missing Activity attribute");
if (method.ContainsGenericParameters)
{
throw new ArgumentException($"{method} contains generic parameters");
}
var parms = method.GetParameters();
return Create(
NameFromAttributed(method, attr),
Expand Down
33 changes: 33 additions & 0 deletions tests/Temporalio.Tests/Activities/ActivityDefinitionTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,23 @@ public async Task CreateAll_ClassOfStaticActivities_CanInvoke()
Assert.Equal(128, await defn.InvokeAsync(new object?[] { 123 }));
}

[Fact]
public void CreateAll_OpenGeneric_Throws()
{
var exc = Assert.ThrowsAny<Exception>(() => ActivityDefinition.CreateAll(
typeof(BadActivityGeneric), new BadActivityGeneric()));
Assert.Contains("contains generic parameters", exc.Message);
}

[Fact]
public async Task CreateAll_ClosedGeneric_CanInvoke()
{
var defn = ActivityDefinition.CreateAll(
typeof(GoodActivityGeneric<string>),
new GoodActivityGeneric<string>("some-val")).Single();
Assert.Equal("some-val", await defn.InvokeAsync(Array.Empty<object?>()));
}

protected static void BadAct1()
{
}
Expand All @@ -174,6 +191,22 @@ public static class GoodActivityClassStatic
public static int MyActivity(int param) => param + 5;
}

public class BadActivityGeneric
{
[Activity]
public T BadActAsync<T>() => throw new NotSupportedException();
}

public class GoodActivityGeneric<T>
{
private readonly T result;

public GoodActivityGeneric(T result) => this.result = result;

[Activity]
public T GoodAsyncAsync() => result;
}

public class BadActivityClassNoActivities
{
public int ActivityWithoutAttribute(int param) => param + 5;
Expand Down

0 comments on commit b33105e

Please sign in to comment.