I am trying to write as much as possible generic code for basic CRUD endpoints, so here is a stripped example of delete endpoint:
public abstract class DeleteEndpoint<TDomain, TId> : ...
{
[HttpDelete(nameof(TDomain) "/{id}")]
public async Task<IActionResult> DeleteAsync(TId id)
{
...
}
}
And then in concrete class, something like this:
public class ConcreteTypeDeleteEndpoint : Base.Crud.DeleteEndpoint<ConcreteType, int>
{
}
the resulting path of HttpDelete should be: "Concretetype/{id}", but instead I get: "TDomain/{id}"
Does nameof work with generic parameters? If not, does anyone have any idea how to achieve this?
CodePudding user response:
nameof
is a compile time feature. At the time that generic type is being compiled, it has no knowledge about which type(s) it may be parameterized with in the future.
Unfortunately, attributes also require values which are constants known at compile-time, which again means there's no way you'll be able to have that attribute use the concrete type name.
You'll either need to make the generic type a base class over which concrete derived classes derive and apply specific attributes e.g.:
public abstract class DeleteEndpoint<TDomain, TId> : ...
{
proteccted async Task<IActionResult> DeleteInternalAsync(TId id)
{
...
}
}
public class ConcreteTypeDeleteEndpoint : Base.Crud.DeleteEndpoint<ConcreteType, int>
{
[HttpDelete(nameof(ConcreteType) "/{id}")]
public Task DeleteAsync(int id) {
return DeleteInternalAsync(id);
}
}
or not use attribute-based routing for these methods.
CodePudding user response:
The nameof(TDomain)
will result in a string with "TDomain". You can use the typeof(TDomain).Name
but that is not a constant and cannot be used in the HttpDelete
Attribute.
void Test<T>()
{
Console.WriteLine(nameof(T));
Console.WriteLine(typeof(T).Name);
}
Test<string>();
Test<int>();
Console.ReadKey();
This program will print:
T
String
T
Int32