首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >得把他们全抓起来!

得把他们全抓起来!
EN

Code Review用户
提问于 2013-12-21 06:34:37
回答 2查看 1.2K关注 0票数 15

本周的挑战本质上是从网络中获取Json数据,并将其反序列化为对象。我没有太多的时间用于这个项目,所以我所拥有的是非常基本的:它在WPF ListView中显示所有pokemons的名称:

下面是窗口的代码:

代码语言:javascript
复制
public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        var service = new PokemonApp.Web.Pokedex();
        var pokemons = service.SelectAllPokemonReferences().OrderBy(pokemon => pokemon.Name);
        DataContext = new MainWindowViewModel { References = pokemons };
    }
}

正如您已经猜到的,有趣的代码在Pokedex类中:

代码语言:javascript
复制
public class Pokedex
{
    public IEnumerable<ResourceReference> SelectAllPokemonReferences()
    {
        string jsonResult = GetJsonResult(PokeDexResultBase.BaseUrl + "pokedex/1/");

        dynamic pokemonRefs = JsonConvert.DeserializeObject(jsonResult);
        ICollection<ResourceReference> references = new List<ResourceReference>();

        foreach (var pokeRef in pokemonRefs.pokemon)
        {
            string uri = PokeDexResultBase.BaseUrl + pokeRef.resource_uri.ToString();
            references.Add(new ResourceReference
                            {
                                Name = pokeRef.name,
                                ResourceUri = new Uri(uri)
                            });
        }

        return references;
    }

    private static string GetJsonResult(string url)
    {
        string result;

        WebRequest request = HttpWebRequest.Create(url);
        request.ContentType = "application/json; charset=utf-8";

        try
        {
            using (var response = request.GetResponse())
            using (var stream = response.GetResponseStream())
            using (var reader = new StreamReader(stream))
            {
                result = reader.ReadToEnd();
            }
        }
        catch (Exception exception)
        {
            result = string.Empty;
            // throw?
        }

        return result;
    }
}

ResourceReference类没有什么特别之处:

代码语言:javascript
复制
public class ResourceReference
{
    public string Name { get; set; }
    public Uri ResourceUri { get; set; }
}

这些非常基本的代码为更复杂的对象奠定了基础:

代码语言:javascript
复制
public abstract class PokeDexResultBase : IPokeDexUri
{
    private readonly string _controller;
    protected PokeDexResultBase(string controller)
    {
        _controller = string.IsNullOrEmpty(controller) ? BaseUrl : controller;
    }

    public static string BaseUrl { get { return "http://pokeapi.co/api/v1/"; } }

    public int Id { get; set; }
    public Uri ResourceUri { get; set; }
    public DateTime Created { get; set; }
    public DateTime Modified { get; set; }

    public virtual string Url { get { return BaseUrl + _controller + (Id == 0 ? string.Empty : Id.ToString()); } }
}

这个基类是由API中具有Id的所有东西继承的:

代码语言:javascript
复制
public class Pokemon : PokeDexResultBase
{
    public Pokemon() : base("pokemon/") { }

    public string Name { get; set; }
    public ICollection<ResourceReference> Abilities { get; set; }
    public ICollection<ResourceReference> EggGroups { get; set; }
    public ICollection<PokemonEvolution> Evolutions { get; set; }
    public ICollection<PokemonMove> Moves { get; set; }
    public ICollection<PokemonType> Types { get; set; }
    public int Attack { get; set; }
    public int CatchRate { get; set; }
    public int Defense { get; set; }
    public int EggCycles { get; set; }
    public string EvolutionYield { get; set; }
    public int ExperienceYield { get; set; }
    public string GrowthRate { get; set; }
    public int Happiness { get; set; }
    public string Height { get; set; }
    public int HitPoints { get; set; }
    public string MaleFemaleRatio { get; set; }
    public int SpecialAttack { get; set; }
    public int SpecialDefense { get; set; }
    public string Species { get; set; }
    public int Speed { get; set; }
    public int Total { get; set; }
    public string Weight { get; set; }
}

public class PokemonEvolution
{
    public int Level { get; set; }
    public string Method { get; set; }
    public Uri ResourceUri { get; set; }
    public string ToPokemonName { get; set; }
}

还有其他涉及的类,但是它们没有什么可回顾的,它们非常类似于Pokemon类。

在扩展代码时,我将向Pokedex类添加更多方法,该类将使用GetJsonResult方法。

我是否很好地分析了API --我的意思是,这段代码是否是反序列化pokemons的坚实基础,并最终使它们能够相互对抗?还有什么可以做得更好呢?有挑剔的人吗?

EN

回答 2

Code Review用户

回答已采纳

发布于 2013-12-21 18:06:46

如果像ResourceReference这样的类在包装API方面是有意义的,那么从UI的角度来看,这就像在UI层中使用POCO:如果数据是通过实体框架从数据库获得的,那么这段代码将显示实体。这是一个基本的实现,但是如果目标是使它成为一个可扩展的“框架”实现,则应该有一个ViewModel类供UI显示,它独立于WebAPI提供的对象;ViewModel不关心ResourceUri --这个属性不是要显示的,而是用于查询API的管道,不属于UI。

Pokedex服务类而言,它看起来可以工作,但是它应该返回ViewModel对象供UI使用,静态GetJsonResult方法可以封装在自己的类中,它将是一个基于HTTP的实现,该实现的作用是获取数据--可能有一个基于SqlServer的实现在数据库中执行同样的任务,其思想是将数据与其数据源分离.但这可能是过头了。

在POCO类中使用Uri增加了不必要的复杂性:它们可以与普通字符串一样保持不变,所以这段代码:

字符串uri = PokeDexResultBase.BaseUrl + pokeRef.resource_uri.ToString();

然后可以这样跳过无用的.ToString()调用:

代码语言:javascript
复制
 string uri = PokeDexResultBase.BaseUrl + pokeRef.resource_uri;

PokeDexResultBase.BaseUrl静态字符串属性作为Pokedex类的静态属性可能更好,然后它将使PokeDexResultBasePokedex紧密耦合,这在某种程度上是有意义的。

此外,为了保持一致性,类PokeDexResultBase应该被称为PokedexResultBase

票数 3
EN

Code Review用户

发布于 2014-04-22 23:59:58

实际上,我最终在反序列化中采用了这种方法。

代码语言:javascript
复制
// Pocos for deserializing
public class PocoAnswer
{ 
    PocoItem item {get; set;}
}

public class PocoItem
{
    String name {get; set; }
    DateTime birthday {get; set; }
}

// Model for binding
public ItemModel
{  
    public readonly PocoItem item; // I wish this to stay private, but json serializer cant get it then
    public ItemModel(PocoItem _item)
    { 
         item = _item;
    }

    [JsonIgnore] // No need to store runtime generated data
    public FormattedInfoString // This is used for binding 
    {
        get 
        {
            return String.Format("My amazing custom string contains name {0} and birth {1}, item.Name, item.Birthday.ToString("yy-mm");
        }
    }
}

当我从服务器得到答案时,我把它推到绑定项中

代码语言:javascript
复制
var result = JsonConvert.DeserializeObject<PocoAnswer>(resultString);
BindableModel = new ItemModel(result.answer.item);

然后在xaml中

代码语言:javascript
复制
<TextBlock Text={Binding BindableModel.FormattedInfoString} \>
票数 2
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/37866

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档