Use Azure Functions in abstract base class?

Viewed 92

I have a FunctionApp running that exposes some entities and they all have the same CRUD operations that follow the same pattern and I was wondering if there was a way I could generalize this in the code. But I'm struggling a bit since everything is declared using attributes and they need to reference constants and those cannot be overridden in a derived class.

I would ideally like to have a base class like this, however I face the problem with the constants.

public abstract class EntityFunctions<T>
{
    protected const string someConstant = "Derived?";
    protected const string someOtherConstant = "Derived?";
    protected readonly ICrudService<T> _crudService;

    public EntityFunctions(ICrudService<T> crudService){
        _crudService = crudService;
    }

    [FunctionName("Create" + someConstant)]
    public async Task<string> Create([HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = someOtherConstant)] T request)
    {
        return _crudService.Create(request);
    }
}

public class MyEntityFunctions : EntityFunctions<MyEntity>{
...
}

Is there a way around this? Some other way to ensure unique function-names and define "base"-routes. Or can functions be registered in another manner?

1 Answers

While FunctionMonkey seems like an interesting project, it is a bit much to pull into my current project. Instead I managed to use T4 templates to do some code generation since my needs are quite simple. Example:

<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ output extension=".Generated.cs" #>
namespace Mynamespace
{
<#
var entities = new List<(string, string)>() { 
("MyEntity1", "my-entity1"), 
("MyEntity1", "my-entity1")
};

foreach (var (entityType, path) in entities)
{
#>
#region <#= entityType #>
    public class Base<#= entityType #>Functions
    {
        protected readonly ICrudService<<#= entityType #>> _crudService;

        public Base<#= entityType #>Functions(ICrudService<<#= entityType #>> crudService)
        {
            _crudService = crudService;
        }

        [FunctionName("Get<#= entityType #>")]
        public async Task<<#= entityType #>> Get([HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "<#= path #>/{ik}")] HttpRequest req, string id)
        {
            return await _crudService.Get(id);
        }
    }
#endregion
<#
}    
#>
}
Related