Generating Handler Interfaces
In Serene, every request handler class has a matching interface that is written by hand:
public interface IRoleSaveHandler : ISaveHandler<MyRow> { }
public class RoleSaveHandler(IRequestContext context)
: SaveRequestHandler<MyRow>(context), IRoleSaveHandler
{
// ...
}
In StartSharp you don't have to write the interface. Place the GenerateInterface attribute on the handler class, and the Serenity.Pro.Coder InterfaceSourceGenerator (a Roslyn source generator) creates the interface for you:
[GenerateInterface]
public class RoleSaveHandler(IRequestContext context) :
SaveRequestHandler<MyRow>(context),
IRoleSaveHandler
{
// ...
}
[GenerateInterface]is aSerenity.Pro.Coderfeature, so it is only available in StartSharp (or projects referencingSerenity.Pro.Coder).
Works for All Request Handler Types
This is not specific to save handlers. The generator recognizes every request handler base class and picks the matching base interface automatically:
| Handler base class | Generated interface |
|---|---|
SaveRequestHandler<TRow> |
ISaveHandler<TRow> |
ListRequestHandler<TRow> |
IListHandler<TRow> |
RetrieveRequestHandler<TRow> |
IRetrieveHandler<TRow> |
DeleteRequestHandler<TRow> |
IDeleteHandler<TRow> |
UndeleteRequestHandler<TRow> |
IUndeleteHandler<TRow> |
So a RoleListHandler, RoleDeleteHandler, or RoleUndeleteHandler marked with [GenerateInterface] gets its IRoleListHandler, IRoleDeleteHandler, IRoleUndeleteHandler, etc. generated the same way.
Naming and Namespace
The generated interface is named I + class name (e.g. IRoleSaveHandler).
It is placed in the same namespace as the handler class, but with a trailing .RequestHandlers suffix removed. So a handler in MyProject.Administration.RequestHandlers gets its interface generated into MyProject.Administration:
// generated by InterfaceSourceGenerator
namespace MyProject.Administration;
public interface IRoleSaveHandler : ISaveHandler<MyRow> { }
Interface Members
Public members of the class become interface members. Mark a member with NonInterfaceMember to exclude it from the generated interface.
For a class that is not a request handler (e.g. an action handler deriving from BaseRequestHandler), the generated interface derives from IRequestHandler and includes the public methods:
[GenerateInterface]
public class TestActionHandler : ITestActionHandler
{
public TestResponse TestAction(TestRequest request) { ... }
}
// generated:
public interface ITestActionHandler : IRequestHandler
{
TestResponse TestAction(TestRequest request);
}