The recommended way to access Azure Durable Entities is through generated proxy objects with the help of interfaces.
The following restrictions, during interface design, are enforced:
- Entity interfaces must be defined in the same assembly as the entity class. This is not detected by the rule.
- Entity interfaces must only define methods.
- Entity interfaces must not contain generic parameters.
- Entity interface methods must not have more than one parameter.
- Entity interface methods must return void, Task, or Task<T>.
If any of these rules are violated, an InvalidOperationException
is thrown at runtime when the interface is used as a type argument to
IDurableEntityContext.SignalEntity<TEntityInterface>
, IDurableEntityClient.SignalEntityAsync<TEntityInterface>
or IDurableOrchestrationContext.CreateEntityProxy<TEntityInterface>
. The exception message explains which rule was broken.
This rule raises an issue in case any of the restrictions above is not respected.
Noncompliant code example
namespace Foo // Noncompliant, must be defined in the same assembly as the entity class that implements it
{
public interface ICounter<T> // Noncompliant, interfaces cannot contain generic parameters
{
string Name { get; set; } // Noncompliant, interface must only define methods
void Add(int amount, int secondParameter); // Noncompliant, methods must not have more than one parameter
int Get(); // Noncompliant, methods must return void, Task, or Task<T>
}
}
namespace Bar
{
public class Counter : ICounter
{
// do stuff
}
public static class AddToCounterFromQueue
{
[FunctionName("AddToCounterFromQueue")]
public static Task Run(
[QueueTrigger("durable-function-trigger")] string input,
[DurableClient] IDurableEntityClient client)
{
var entityId = new EntityId("Counter", "myCounter");
int amount = int.Parse(input);
return client.SignalEntityAsync<ICounter>(entityId, proxy => proxy.Add(amount, 10));
}
}
}
Compliant solution
namespace Bar
{
public interface ICounter
{
void Add(int amount);
Task<int> Get();
}
}
namespace Bar
{
public class Counter : ICounter
{
// do stuff
}
public static class AddToCounterFromQueue
{
[FunctionName("AddToCounterFromQueue")]
public static Task Run(
[QueueTrigger("durable-function-trigger")] string input,
[DurableClient] IDurableEntityClient client)
{
var entityId = new EntityId("Counter", "myCounter");
int amount = int.Parse(input);
return client.SignalEntityAsync<ICounter>(entityId, proxy => proxy.Add(amount));
}
}
}