2016-11-09 110 views
0

我开始围绕面向对象的编程(过去一直比较流程化)和MVVM开始。我对于本地应用程序的结构(模型等的类)有点自信,但我很担心连接到外部API并检索JSON结果(我知道如何连接,但我在说话关于项目结构等)。我已经阅读了关于外观和服务的内容,但是看起来不同的人对事物的结构有所不同。我相信没有普遍的规则,但有没有“最佳做法”?在C#UWP应用程序中何时使用API​​调用

就在我头顶,似乎有一个API类是有道理的。从数据模型到连接到API的所有内容都可以放在那里。尽管如此,我认为人们通过视图模型来建立连接。

我只是在寻找一些输入。感谢任何方向。

+0

所以,使用'接口'似乎很普遍。 – doubleJ

回答

1

你可以想象,有很多方法可以做到这一点。任何设计都可能有其优点和缺点,而且你可能会用经验来解决这些问题。

一个简单的方法是拥有一个“服务”类,它是您的代码对外部服务的正面。它的接口可能如此简单:

interface MyService 
{ 
    void SomeOperation(int someValue); 
    string AnotherOperation(double anotherValue); 
} 

实现此服务的类实质上是传递到外部服务。它将负责封装访问服务的技术堆栈,例如HTTP REST客户端。

理想地,这完全包裹使用服务(如HTTP,JSON等东西)的技术方面和仅露出逻辑它(以及命名方法方面,接受并返回域对象,而不是JSON字符串等)。这种方式应该换掉技术,你仍然保留相同的语义业务含义,只需要改变该接口后面的一个实现。

至于在哪里使用服务类,这往往是一个意见问题,真正取决于最终更有意义,更容易在代码中支持。一派思想是让模型在内部使用服务类,一切都与模型进行交互,另一种方法是在更多的程序代码中使用服务和模型。我个人认为前者在MVVM中更有意义,后者在MVC中更有意义。但你的里程可能会有所不同

如果可能的话,我会建议尝试直接在模型中使用服务,因为任何过程代码都需要在某个地方居住,而在MVVM模式中,您可能会发现自己在错误的地方出现“鞋尖”。如果您也想要这样做,那么您如何处理诸如服务在模型中的依赖注入等完全是另一个话题。

+0

一旦你创建了'interface',你就必须创建另一个继承它的类。那是对的吗?我见过很多'IServiceName'和'ServiceName'(其中'ServiceName:IServiceName')。 – doubleJ

1

没有正确的答案具体..这取决于你的应用程序已经结构化和你想要做什么。对于我们的生产UWP的应用程序,几乎所有的API调用的是业务对象下载调用,因此我们设置了每次通话的一类,其中每个实现一个共同的接口,像这样:

interface IDownloadMethod<T> : where T : IPersistable { 
    string WebServiceBaseURL { get; set; } 
    IEnumerable<T> Download(); 
    Action<IEnumerable> RepositoryMethod { get; } 
} 

...其中IPersistable是一个表示这些调用返回的数据的接口。

我们创建了一个抽象基类,它实现IDownloadMethod<T>,与所有的通用功能:

public class AbstractDownloadMethod<T> : IDownloadMethod<T> where T : IPersistable { 
    // default implementations of all needed methods 

    // the most important one: 
    IEnumerable<T> Download() { 
     // implementation 
    } 
} 

,然后将每个下载方法成为一个非常简单的类:

internal class DownloadSomeBusinessObject : AbstractDownloadMethod<SomeBusinessObject> 
{ 
    public DownloadSomeBusinessObject (Action<IEnumerable> handler, string webServiceBaseURL, LoginCredential credential) 
     : base(handler, webServiceBaseURL, credential) 
    { 
     ActionURL = @"someBusinessObject/"; 
    } 
} 

我们还有很长这样的API调用列表,所以我们有一个Controller类遍历所有这些类,并调用它们的Download()方法,然后将结果保存到存储库:

// you need to populate methodsList first with all the methods you want to call, then... 
foreach (IDownloadMethod<IPersistable> method in methodsList) 
{ 
    Task<IEnumerable<IPersistable>> task = Task.Run(() => method.Download()); 
    TaskAwaiter<IEnumerable<IPersistable>> awaiter = task.GetAwaiter(); 
    while (!awaiter.IsCompleted) 
    { // busy waiting is terrible.. we know 
    } 
    IList<IPersistable> genericList = awaiter.GetResult().ToList(); 

    if (method.RepositoryMethod != null) 
    { 
     method.RepositoryMethod(genericList); 
    } 
} 
相关问题