graphql-platform
graphql-platform copied to clipboard
Add support for the default interface method implementation
Product
Hot Chocolate
Is your feature request related to a problem?
Lets imagine we want the Hot Chocolate to produce a schema like:
interface IChannel {
id: ID!
description: String!
status: ChannelStatus!
}
union IAnotherChannel = ChannelTypeB | ChannelTypeC
type ChannelTypeA implements IChannel {
id: ID!
description: String!
status: ChannelStatus!
ip: String!
}
type ChannelTypeB implements IChannel {
id: ID!
description: String!
status: ChannelStatus!
port: String!
}
type ChannelTypeC implements IChannel {
id: ID!
description: String!
status: ChannelStatus!
adapter: String!
}
I have to use records in my project. So I did somethink like:
[GraphQLName("IChannel")]
public interface IChannelDto
{
[ID]
Guid Id { get; init; }
string Description { get; init; }
#region workaround
// TODO: delete after Hot Chocolate Team fixes one of two issue:
// - ExtendObjectType should extend interface and all derived classes
// - interface default methods implementations must be used in derived classes
Task<ChannelStatus> GetStatusAsync() { throw new NotImplementedException(); }
#endregion
}
[ExtendObjectType(typeof(IChannelDto))]
public class ChannelResolvers
{
public async Task<ChannelStatus> GetStatusAsync()
{
// Do some stuff
}
}
[GraphQLName("ChannelTypeA")]
public record ChannelTypeADto
(
[property: ID] Guid Id,
string Description,
string IP,
) : IChannelDto;
[UnionType("IAnotherChannel")]
public interface IAnotherChannelDto : IChannelDto { };
[GraphQLName("ChannelTypeB")]
public record ChannelTypeBDto
(
[property: ID] Guid Id,
string Description,
string Port,
) : IAnotherChannelDto;
[GraphQLName("ChannelTypeC")]
public record ChannelTypeCDto
(
[property: ID] Guid Id,
string Description,
string Adapter,
) : IAnotherChannelDto;
Here is a problem:
- The ExtendObjectType annotation does not extend interfaces by design but I need it, so I made a workaround. That stub function is never called and I only need it to create the schema.
- I can't just remove the class with the ExtendObjectType annotation and put the default implementation inside the interface. Hot chocolate want me to add a
Status
field inside all derived records.
I must use both the ExtendObjectType annotation and that stub default implementation in the interface. If I could replace records with classes, I would do something like:
[InterfaceType("IChannel")]
public abstract class ChannelDto
{
[ID]
public Guid Id { get; init; }
public string Description { get; init; }
public async Task<ChannelStatus> GetStatusAsync()
{
// Do some stuff
}
}
[GraphQLName("ChannelTypeA")]
public class ChannelTypeADto : ChannelDto
{
public string IP { get; init; }
}
[UnionType("IAnotherChannel")]
public abstract class AnotherChannelDto : ChannelDto { };
[GraphQLName("ChannelTypeB")]
public class ChannelTypeBDto : AnotherChannelDto
{
public string Port { get; init; }
}
[GraphQLName("ChannelTypeC")]
public class ChannelTypeCDto : AnotherChannelDto
{
public string Adapter { get; init; }
}
This works nice!
The solution you'd like
One of:
- Let the ExtendObjectType annotation extend interfaces.
- Add support for the default method implementation in the schema inference algorithm.