Skip to content

Commit

Permalink
Add DIGraph attribute
Browse files Browse the repository at this point in the history
  • Loading branch information
Shane32 committed Nov 3, 2021
1 parent 5fa69ac commit a59edf3
Show file tree
Hide file tree
Showing 4 changed files with 124 additions and 1 deletion.
28 changes: 28 additions & 0 deletions src/GraphQL.DI/DIGraphAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Text;

namespace GraphQL.DI
{
/// <summary>
/// Marks a method's return graph type to be a specified DI graph type.
/// Useful when the return type cannot be inferred (often when it is of type <see cref="object"/>).
/// </summary>
[AttributeUsage(AttributeTargets.Method, Inherited = false)]
public class DIGraphAttribute : Attribute
{
/// <summary>
/// Marks a method's return graph type to be a specified DI graph type.
/// </summary>
/// <param name="graphBaseType">A type that inherits <see cref="DIObjectGraphBase"/>.</param>
public DIGraphAttribute(Type graphBaseType)
{
GraphBaseType = graphBaseType;
}

/// <summary>
/// The DI graph type that inherits <see cref="DIObjectGraphBase"/>.
/// </summary>
public Type GraphBaseType { get; }
}
}
2 changes: 1 addition & 1 deletion src/GraphQL.DI/DIObjectGraphBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public abstract class DIObjectGraphBase<TSource> : IDIObjectGraphBase<TSource>,
/// This is a required base type of all DI-created graph types. <see cref="DIObjectGraphBase{TSource}"/> may be
/// used when the <see cref="IResolveFieldContext.Source"/> type is not <see cref="object"/>.
/// </summary>
public abstract class DIObjectGraphBase : DIObjectGraphBase<object>, IDIObjectGraphBase<object>
public abstract class DIObjectGraphBase : DIObjectGraphBase<object>
{
}
}
6 changes: 6 additions & 0 deletions src/GraphQL.DI/DIObjectGraphType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,12 @@ protected virtual TypeInformation ApplyAttributes(TypeInformation typeInformatio
}
if (member.IsDefined(typeof(IdAttribute), false))
typeInformation.GraphType = typeof(IdGraphType);
else if (member.GetCustomAttributes(typeof(DIGraphAttribute), false).SingleOrDefault() is DIGraphAttribute diGraphAttribute) {
var iface = diGraphAttribute.GraphBaseType.GetInterfaces().FirstOrDefault(x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof(IDIObjectGraphBase<>));
if (iface == null)
throw new InvalidOperationException($"Method '{typeInformation.ParameterInfo.Member.DeclaringType.Name}.{typeInformation.ParameterInfo.Member.Name}' is marked with [DIGraph] specifying type '{diGraphAttribute.GraphBaseType.Name}' which does not inherit {nameof(IDIObjectGraphBase)}<T>.");
typeInformation.GraphType = typeof(DIObjectGraphType<,>).MakeGenericType(diGraphAttribute.GraphBaseType, iface.GetGenericArguments()[0]);
}
return typeInformation;
}

Expand Down
89 changes: 89 additions & 0 deletions src/Tests/DIObjectGraphTypeTests/Field.cs
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,22 @@ public class CRequired : DIObjectGraphBase<object>
public static string Field1() => "hello";
}

[Fact]
public void InheritedRequired()
{
Configure<CInheritedRequired, object>();
VerifyField("Field1", false, false, "hello");
Verify(false);
}

public class CInheritedRequired : DIObjectGraphBase<object>
{
[MyRequired]
public static string Field1() => "hello";
}

public class MyRequiredAttribute : RequiredAttribute { }

[Fact]
public async Task RequiredTask()
{
Expand Down Expand Up @@ -349,6 +365,79 @@ public class CIdTypeNonNull : DIObjectGraphBase<object>
public static int Field1() => 2;
}

[Fact]
public void IdListType()
{
Configure<CIdListType, object>();
VerifyField("Field1", typeof(ListGraphType<IdGraphType>), false, new[] { "hello" });
Verify(false);
}

public class CIdListType : DIObjectGraphBase<object>
{
[Id]
public static string[] Field1() => new[] { "hello" };
}

[Fact]
public void DIGraphType()
{
Configure<CDIGraphType, object>();
VerifyField("Field1", typeof(DIObjectGraphType<CDIGraphType2, object>), false, "hello");
Verify(false);
}

public class CDIGraphType2 : DIObjectGraphBase<object>
{
public static string Field1() => "hello";
}

public class CDIGraphType : DIObjectGraphBase<object>
{
[DIGraph(typeof(CDIGraphType2))]
public static string Field1() => "hello";
}

[Fact]
public void DIGraphTypeNonNull()
{
Configure<CDIGraphTypeNonNull, object>();
VerifyField("Field1", typeof(NonNullGraphType<DIObjectGraphType<CDIGraphType2, object>>), false, 2);
Verify(false);
}

public class CDIGraphTypeNonNull : DIObjectGraphBase<object>
{
[DIGraph(typeof(CDIGraphType2))]
public static int Field1() => 2;
}

[Fact]
public void DIGraphListType()
{
Configure<CDIGraphListType, object>();
VerifyField("Field1", typeof(ListGraphType<DIObjectGraphType<CDIGraphType2, object>>), false, new[] { "hello" });
Verify(false);
}

public class CDIGraphListType : DIObjectGraphBase<object>
{
[DIGraph(typeof(CDIGraphType2))]
public static string[] Field1() => new[] { "hello" };
}

[Fact]
public void DIGraphTypeInvalid()
{
Should.Throw<InvalidOperationException>(() => Configure<CDIGraphTypeInvalid, object>());
}

public class CDIGraphTypeInvalid : DIObjectGraphBase<object>
{
[DIGraph(typeof(string))]
public static string Field1() => "hello";
}

[Fact]
public async Task Concurrent()
{
Expand Down

0 comments on commit a59edf3

Please sign in to comment.