首先要使用GraphQL安装三个包
GraphQL
GraphQL.Server.Transports.AspNetCore
GraphQL.Server.Ui.Playground
定义基础类
public class Account
{
public Guid Id { get; set; }
public TypeOfAccount Type { get; set; }
public string Description { get; set; }
public Guid PersonId { get; set; }
public Person Person { get; set; }
}
public enum TypeOfAccount
{
Invalid,
Free,
Junior,
Intermediate
}
public class Person
{
public Guid Id { get; set; }
public string Name { get; set; }
public string Address { get; set; }
public ICollection<Account> Accounts { get; set; }
}
上下文
public class SampleContext
{
public List<Person> Persons { get; set; }
public List<Account> Accounts { get; set; }
public SampleContext()
{
var ids = new[] { Guid.NewGuid(), Guid.NewGuid() };
Accounts = new List<Account>
{
new Account
{
Id = Guid.NewGuid(),
Type = TypeOfAccount.Junior,
Description = "初级会员",
PersonId = ids[0]
},
new Account
{
Id = Guid.NewGuid(),
Type = TypeOfAccount.Intermediate,
Description = "中级会员",
PersonId = ids[1]
},
new Account
{
Id = Guid.NewGuid(),
Type = TypeOfAccount.Free,
Description = "免费会员",
PersonId = ids[1]
}
};
Persons = new List<Person>
{
new Person
{
Id = ids[0],
Name = "张三",
Address = "北京"
},
new Person
{
Id = ids[1],
Name = "李四",
Address = "上海"
}
};
}
}
仓储
public interface IAccountRepository
{
IEnumerable<Account> GetAllAccountsPerson(Guid personId);
}
public interface IPersonRepository
{
IEnumerable<Person> GetAll();
Person GetById(Guid id);
}
public class AccountRepository : IAccountRepository
{
private readonly SampleContext _context;
public AccountRepository(SampleContext context)
{
_context = context;
}
public IEnumerable<Account> GetAllAccountsPerson(Guid personId)
{
return _context.Accounts.Where(a => a.PersonId == personId);
}
}
public class PersonRepository : IPersonRepository
{
private readonly SampleContext _context;
public PersonRepository(SampleContext context)
{
_context = context;
}
public IEnumerable<Person> GetAll()
{
return _context.Persons;
}
public Person GetById(Guid id)
{
return _context.Persons.SingleOrDefault(p => p.Id == id);
}
}
GraphQL相关类
public class AccountTypeEnumType : EnumerationGraphType<TypeOfAccount>
{
public AccountTypeEnumType()
{
Name = "Type";
}
}
public class AccountType : ObjectGraphType<Account>
{
public AccountType()
{
Field(x => x.Id, type: typeof(IdGraphType));
Field(x => x.Description);
Field(x => x.PersonId, type: typeof(IdGraphType));
Field<AccountTypeEnumType>("Type", "Account类型对象的枚举");
}
}
public class PersonType : ObjectGraphType<Person>
{
public PersonType(IAccountRepository repository)
{
Field(x => x.Id, type: typeof(IdGraphType));
Field(x => x.Name);
Field(x => x.Address);
Field<ListGraphType<AccountType>>(
name: "accounts",
resolve: context => repository.GetAllAccountsPerson(context.Source.Id));
}
}
public class AppSchema: Schema
{
public AppSchema(IDependencyResolver resolver)
:base(resolver)
{
Query = resolver.Resolve<AppQuery>();
}
}
public class AppQuery: ObjectGraphType
{
public AppQuery(IPersonRepository repository)
{
Field<ListGraphType<PersonType>>(
"persons",
resolve: context => repository.GetAll()
);
Field<PersonType>(
"person",
arguments: new QueryArguments(new QueryArgument<NonNullGraphType<IdGraphType>> { Name = "personId" }),
resolve: context =>
{
var personId = context.GetArgument<string>("personId");
if (Guid.TryParse(personId, out var id)) return repository.GetById(id);
context.Errors.Add(new ExecutionError("错误的GUID格式"));
return null;
}
);
}
}
在asp.net core中使用
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddSingleton<SampleContext>();
services.AddScoped<IPersonRepository, PersonRepository>();
services.AddScoped<IAccountRepository, AccountRepository>();
services.AddScoped<IDependencyResolver>(s => new FuncDependencyResolver(s.GetRequiredService));
services.AddScoped<AppSchema>();
services.AddGraphQL(o => { o.ExposeExceptions = false; })
.AddGraphTypes(ServiceLifetime.Scoped);
services.Configure<KestrelServerOptions>(options =>
{
options.AllowSynchronousIO = true;
});
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseRouting();
app.UseAuthorization();
app.UseGraphQL<AppSchema>();
app.UseGraphQLPlayground(options: new GraphQLPlaygroundOptions());
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
用localhost:5000/ui/playgroud来查看服务页面
客户端的使用如下:
public class PersonConsumer
{
private readonly IGraphQLClient _client;
public PersonConsumer(IGraphQLClient client)
{
_client = client;
}
public async Task<List<Person>> GetAll()
{
var query = new GraphQLRequest
{
Query = @"
query personsQuery{
persons {
id,
name,
address,
accounts {
id,
type,
description
}
}
}"
};
var response = await _client.SendQueryAsync<ResponsePersonCollectionType>(query);
return response.Data.Persons;
}
public async Task<Person> Get(string id)
{
var query = new GraphQLRequest
{
Query = @"
query personQuery($personID: ID!) {
person(personId: $personID) {
id,
name,
address,
accounts {
id,
type,
description
}
}
}",
Variables = new { personID = id }
};
var response = await _client.SendQueryAsync<ResponsePersonType>(query);
return response.Data.Person;
}
}
[Route("api/[controller]")]
[ApiController]
public class PersonController : ControllerBase
{
private readonly PersonConsumer _personConsumer;
public PersonController(PersonConsumer personConsumer)
{
_personConsumer = personConsumer;
}
public async Task<IActionResult> Get()
{
var persons = await _personConsumer.GetAll();
return Ok(persons);
}
[HttpGet("{id}")]
public async Task<IActionResult> Get(string id)
{
var person = await _personConsumer.Get(id);
return Ok(person);
}
}
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddScoped<IGraphQLClient>(s =>
new GraphQLHttpClient(Configuration["GraphQLUri"], new NewtonsoftJsonSerializer()));
services.AddScoped<PersonConsumer>();
services.AddControllers();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}