Skip to content

Commit

Permalink
Merge pull request #12 from graphql-dotnet/dependency-injection
Browse files Browse the repository at this point in the history
Dependency Injection Fixes
  • Loading branch information
tlil authored Jan 19, 2017
2 parents d27b4ab + b9190e4 commit 82705bb
Show file tree
Hide file tree
Showing 13 changed files with 264 additions and 17 deletions.
27 changes: 26 additions & 1 deletion src/GraphQL.Conventions/Adapters/Engine/GraphQLEngine.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using GraphQL.Conventions.Adapters.Engine.Listeners.DataLoader;
Expand Down Expand Up @@ -45,10 +46,34 @@ public INodeVisitor Validate(ValidationContext context)
}
}

private class WrappedDependencyInjector : IDependencyInjector
{
private readonly Func<System.Type, object> _typeResolutionDelegate;

public WrappedDependencyInjector(Func<System.Type, object> typeResolutionDelegate)
{
_typeResolutionDelegate = typeResolutionDelegate;
}

public object Resolve(System.Reflection.TypeInfo typeInfo)
{
return _typeResolutionDelegate(typeInfo.AsType());
}
}

public GraphQLEngine(Func<System.Type, object> typeResolutionDelegate = null)
{
_constructor = new SchemaConstructor<ISchema, IGraphType>(_graphTypeAdapter, _typeResolver);
_constructor.TypeResolutionDelegate = typeResolutionDelegate;
if (typeResolutionDelegate != null)
{
_typeResolver.DependencyInjector = new WrappedDependencyInjector(typeResolutionDelegate);
_constructor.TypeResolutionDelegate = typeResolutionDelegate;
}
else
{
_constructor.TypeResolutionDelegate = type =>
_typeResolver?.DependencyInjector?.Resolve(type.GetTypeInfo()) ?? Activator.CreateInstance(type);
}
}

public void BuildSchema(params System.Type[] schemaTypes)
Expand Down
22 changes: 19 additions & 3 deletions src/GraphQL.Conventions/Adapters/GraphTypeAdapter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,20 @@ public class GraphTypeAdapter : IGraphTypeAdapter<ISchema, IGraphType>

public ISchema DeriveSchema(GraphSchemaInfo schemaInfo)
{
foreach (var type in schemaInfo.Types)
var types = schemaInfo
.Types
.Where(t => !t.IsIgnored && !t.Interfaces.Any(iface => iface.IsIgnored))
.ToList();
foreach (var type in types)
{
DeriveType(type);
}
var interfaces = schemaInfo.Types.Where(t => !t.IsIgnored && t.IsInterfaceType && t.PossibleTypes.Any());
var possibleTypes = interfaces.SelectMany(t => t.PossibleTypes).Distinct();
var interfaces = types
.Where(t => t.IsInterfaceType && t.PossibleTypes.Any());
var possibleTypes = interfaces
.Where(t => !t.IsIgnored)
.SelectMany(t => t.PossibleTypes)
.Distinct();
var schema = new Schema(DeriveTypeFromTypeInfo)
{
Query = DeriveOperationType(schemaInfo.Query),
Expand Down Expand Up @@ -178,6 +186,10 @@ private TReturnType ConstructType<TReturnType>(Type template, GraphTypeInfo type
{
var typeParameter = typeInfo.GetTypeRepresentation();
var type = CreateTypeInstance<TReturnType>(template.MakeGenericType(typeParameter.AsType()));
if (type == null)
{
return default(TReturnType);
}
type.Name = typeInfo.Name;
type.Description = typeInfo.Description;
type.DeprecationReason = typeInfo.DeprecationReason;
Expand All @@ -197,6 +209,10 @@ private IGraphType ConstructEnumerationType(GraphTypeInfo typeInfo)
private IGraphType ConstructInterfaceType(GraphTypeInfo typeInfo)
{
var graphType = ConstructType<IInterfaceGraphType>(typeof(Types.InterfaceGraphType<>), typeInfo);
if (typeInfo.IsIgnored)
{
return WrapNonNullableType(typeInfo, graphType);
}
foreach (var possibleType in typeInfo.PossibleTypes.Select(t => DeriveType(t) as IObjectGraphType))
{
graphType.AddPossibleType(possibleType);
Expand Down
6 changes: 3 additions & 3 deletions src/GraphQL.Conventions/CommonAssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
[assembly: AssemblyProduct("GraphQL.Conventions")]
[assembly: AssemblyCopyright("Copyright 2016-2017 Tommy Lillehagen. All rights reserved.")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyVersion("1.0.7.0")]
[assembly: AssemblyFileVersion("1.0.7.0")]
[assembly: AssemblyInformationalVersion("1.0.7.0")]
[assembly: AssemblyVersion("1.0.8.0")]
[assembly: AssemblyFileVersion("1.0.8.0")]
[assembly: AssemblyInformationalVersion("1.0.8.0")]
[assembly: CLSCompliant(false)]

[assembly: InternalsVisibleTo("GraphQL.Conventions.Tests")]
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,7 @@ public GraphArgumentInfo(ITypeResolver typeResolver, ParameterInfo parameter = n
new List<IExecutionFilterAttribute>();

public bool IsInjected { get; set; }

public override string ToString() => $"{nameof(GraphArgumentInfo)}:{Name}";
}
}
2 changes: 2 additions & 0 deletions src/GraphQL.Conventions/Types/Descriptors/GraphFieldInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,7 @@ public GraphFieldInfo(ITypeResolver typeResolver, MemberInfo field = null)
new List<IExecutionFilterAttribute>();

public bool IsMethod => AttributeProvider is MethodInfo;

public override string ToString() => $"{nameof(GraphFieldInfo)}:{Name}";
}
}
2 changes: 2 additions & 0 deletions src/GraphQL.Conventions/Types/Descriptors/GraphSchemaInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,5 +38,7 @@ public object this[string key]
}
return defaultValue;
}

public override string ToString() => nameof(GraphSchemaInfo);
}
}
2 changes: 2 additions & 0 deletions src/GraphQL.Conventions/Types/Descriptors/GraphTypeInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ public void AddUnionType(GraphTypeInfo typeInfo)
AddPossibleType(typeInfo);
}

public override string ToString() => $"{nameof(GraphTypeInfo)}:{Name}";

private void DeriveMetaData()
{
var type = TypeRepresentation;
Expand Down
25 changes: 20 additions & 5 deletions src/GraphQL.Conventions/Types/Resolution/ObjectReflector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public GraphSchemaInfo GetSchema(TypeInfo typeInfo)
schemaInfo.Subscription = subscriptionField != null
? GetType(subscriptionField.PropertyType.GetTypeInfo())
: null;
schemaInfo.Types.AddRange(_typeCache.Entities);
schemaInfo.Types.AddRange(_typeCache.Entities.Where(t => IsValidType(t.GetTypeRepresentation())));

return schemaInfo;
}
Expand All @@ -73,12 +73,21 @@ public GraphTypeInfo GetType(TypeInfo typeInfo)
return type;
}

var isInjectedType = type.TypeRepresentation.AsType() == typeof(IResolutionContext);
if (typeInfo.IsGenericParameter || typeInfo.ContainsGenericParameters)
{
type.IsIgnored = true;
return type;
}

var isInjectedType =
type.TypeRepresentation.AsType() == typeof(IResolutionContext) ||
type.TypeRepresentation.AsType() == typeof(IUserContext);

if (!type.IsEnumerationType &&
!type.IsScalarType &&
!type.IsInterfaceType &&
!type.IsUnionType &&
!type.IsIgnored &&
!isInjectedType)
{
DeriveInterfaces(type);
Expand All @@ -93,14 +102,14 @@ public GraphTypeInfo GetType(TypeInfo typeInfo)

_metaDataHandler.DeriveMetaData(type, GetTypeInfo(typeInfo));

if (type.IsInterfaceType && !isInjectedType)
if (type.IsInterfaceType && !type.IsIgnored && !isInjectedType)
{
var iface = type.GetTypeRepresentation();
var types = iface.Assembly.GetTypes().Where(t => iface.IsAssignableFrom(t));
foreach (var t in types)
{
var ti = t.GetTypeInfo();
if (!ti.IsInterface)
if (!ti.IsInterface && IsValidType(ti))
{
GetType(ti);
}
Expand Down Expand Up @@ -190,6 +199,10 @@ private IEnumerable<GraphArgumentInfo> GetArguments(MethodInfo methodInfo)
.Select(DeriveArgument)
?? new GraphArgumentInfo[0])
{
if (argument.IsInjected)
{
argument.Type.IsIgnored = true;
}
yield return argument;
}
}
Expand Down Expand Up @@ -272,7 +285,9 @@ private GraphEnumMemberInfo DeriveEnumValue(string name, TypeInfo type)
private static bool IsValidType(TypeInfo typeInfo)
{
return typeInfo.Namespace != nameof(System) &&
!typeInfo.Namespace.StartsWith($"{nameof(System)}.");
!typeInfo.Namespace.StartsWith($"{nameof(System)}.") &&
!typeInfo.ContainsGenericParameters &&
!typeInfo.IsGenericType;
}

private static bool IsValidMember(MemberInfo memberInfo)
Expand Down
2 changes: 1 addition & 1 deletion src/GraphQL.Conventions/project.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"version": "1.0.7-*",
"version": "1.0.8-*",
"description": "GraphQL Conventions for .NET",
"authors": [
"Tommy Lillehagen"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
using System;
using GraphQL.Conventions.Adapters.Engine;
using GraphQL.Conventions.Tests.Templates;
using GraphQL.Conventions.Tests.Templates.Extensions;
using GraphQL.Conventions.Types;
using Xunit;

namespace GraphQL.Conventions.Tests.Adapters.Engine
{
public class AbstractTypeConstructionTests : TestBase
{
[Fact]
public void Can_Construct_And_Describe_Schema_From_Abstract_Types()
{
var engine = new GraphQLEngine();
engine.BuildSchema(typeof(SchemaDefinition<Query>));
var schema = engine.Describe();
schema.ShouldEqualWhenReformatted(@"
type Query {
commonField: Date!
someOtherField: String
}
");
}

[Fact]
public async void Can_Execute_Query_On_Schema_From_Abstract_Types()
{
var engine = new GraphQLEngine();
engine.BuildSchema(typeof(SchemaDefinition<Query>));
var result = await engine
.NewExecutor()
.WithQueryString("{ commonField someOtherField }")
.EnableValidation()
.Execute();

result.ShouldHaveNoErrors();
result.Data.ShouldHaveFieldWithValue("commonField", default(DateTime));
result.Data.ShouldHaveFieldWithValue("someOtherField", string.Empty);
}

abstract class EntityQuery<T>
{
public T CommonField => default(T);
}

class Query : EntityQuery<DateTime>
{
public string SomeOtherField => string.Empty;
}
}
}
Loading

0 comments on commit 82705bb

Please sign in to comment.