public void Register(ApiSchema schema)
        {
            var methods = typeof(TInterface).GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public);

            foreach (var methodInfo in methods)
            {
                if (methodInfo.Name == nameof(IOperation.Register))
                {
                    continue;
                }

                var isQuery    = methodInfo.CustomAttributes.Any(a => a.AttributeType == typeof(QueryAttribute));
                var isMutation = methodInfo.CustomAttributes.Any(a => a.AttributeType == typeof(MutationAttribute));
                if (!isQuery && !isMutation)
                {
                    isQuery = true;
                }

                var apiOperation = isQuery ? schema.Query : schema.Mutation;
                var parameters   = methodInfo.GetParameters();
                if (parameters.Length != 1)
                {
                    throw new GraphException($"An operation method must have one input parameter. Operation: {typeof(TInterface).Name}.{methodInfo.Name}");
                }
                var fieldName        = methodInfo.Name.ToCamelCase();
                var fieldDescription = "";
                var queryArguments   = GraphArguments.FromModel(parameters[0].ParameterType).GetQueryArguments();
                // Add function as operation
                var returnType = TypeLoader.GetBaseType(methodInfo.ReturnType, out bool isList);
                schema.MapOutput(returnType, autoMapChildren: true, overwriteMap: false);
                var graphType = TypeLoader.GetGraphType(methodInfo.ReturnType);
                apiOperation.Field(graphType, fieldName, fieldDescription, queryArguments, context =>
                {
                    var inputModel = ApiOperation.GetInputFromContext(context, parameters[0].ParameterType);
                    ValidationError.ValidateObject(inputModel);
                    var operationValues = new OperationValues()
                    {
                        Context            = context,
                        FieldName          = fieldName,
                        Fields             = new InputField[0],
                        FunctionAttributes = methodInfo.GetCustomAttributes(true).OfType <Attribute>().ToArray(),
                        Input = inputModel,
                    };
                    operationValues = schema.Container.GetInstance <ApiSchema>().RunOperationFilters(OperationFilterType.Pre, operationValues);

                    var graphClient = GetGraphClient();
                    var query       = graphClient.AddSelectionQuery(fieldName, inputModel, context.FieldAst.SelectionSet.Selections.OfType <Field>());
                    var graphOutput = isQuery ? graphClient.RunQueries() : graphClient.RunMutations();
                    if (graphOutput.HasErrors)
                    {
                        graphOutput.ThrowErrors();
                    }
                    operationValues.Output = query.Data.ToObject(methodInfo.ReturnType);
                    if (PostOperations.ContainsKey(fieldName))
                    {
                        operationValues.Output = PostOperations[fieldName](context, fieldName, operationValues.Output);
                    }
                    operationValues = schema.Container.GetInstance <ApiSchema>().RunOperationFilters(OperationFilterType.Post, operationValues);
                    return(operationValues.Output);
                });
            }
        }
        protected void Application_Start()
        {
            var container = new GraphQLContainer();

            container.Options.AllowOverridingRegistrations = false;
            container.Options.DefaultScopedLifestyle       = new AsyncScopedLifestyle();
            container.RegisterWebApiControllers(GlobalConfiguration.Configuration);

            container.Register <IContainer>(() => container);
            var data = new Data();

            container.Register <Data>(() => data);
            var authorizationMap = new AuthorizationMap()
            {
                AllowMissingAuthorizations = true
            };

            container.Register <AuthorizationMap>(() => authorizationMap);

            //Graph Schema
            container.Register <ResolverInfoManager>(Lifestyle.Scoped);
            container.RegisterSingleton <ApiSchema>(() =>
            {
                var apiSchema = new ApiSchema(container);
                apiSchema.AddPropertyFilter <string>((context, propertyInfo, name, value) =>
                {
                    Debug.WriteLine($"PropertyFilter for {name}");
                    return(value);
                });
                apiSchema.AddPropertyFilter <Uri>((context, propertyInfo, name, value) =>
                {
                    Debug.WriteLine($"Replacing host for Uri {value}");
                    var builder = new UriBuilder(value)
                    {
                        Host = "www.replacement.com"
                    };
                    return(builder.Uri);
                });
                apiSchema.AddPropertyFilter((context, propertyInfo, name, value) =>
                {
                    Debug.WriteLine($"Generic property filter");
                    return(value);
                });

                // map a type with a type mapping
                //apiSchema.MapOutput<Lego, LegoMap>();
                apiSchema.MapAssemblies(Assembly.GetAssembly(typeof(HumanObject)));

                // map a type without GraphObject implementation
                //apiSchema.MapOutput<Robot, Output.RobotOutput>();
                apiSchema.MapOutput <RobotOutput>(autoMapChildren: true, overwriteMap: true);

                // map an operation without IOperation implementation
                var proxy = apiSchema.Proxy <ILegoOperation>(() => new GraphClient("http://localhost:51365/api", new HttpClient()));
                //proxy.AddPostOperation(nameof(ILegoOperation.Lego), (context, name, value) =>
                //{
                //    Debug.WriteLine($"PostOperation for {name}");
                //    return value;
                //});
                proxy.AddPostOperation(i => nameof(i.Lego), (context, name, value) =>
                {
                    Debug.WriteLine($"PostOperation for {name}");
                    return(value);
                });
                apiSchema.Lock();
                return(apiSchema);
            });
            container.Verify();

            GlobalConfiguration.Configuration.DependencyResolver = new SimpleInjectorWebApiDependencyResolver(container);
            GlobalConfiguration.Configuration.MapHttpAttributeRoutes();
            GlobalConfiguration.Configuration.EnsureInitialized();

            GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings = new JsonSerializerSettings()
            {
                TypeNameHandling      = TypeNameHandling.None,
                Formatting            = Formatting.Indented,
                ContractResolver      = new CamelCasePropertyNamesContractResolver(),
                ReferenceLoopHandling = ReferenceLoopHandling.Ignore
            };
            GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.Converters.Add(new StringEnumConverter());
        }