FreshMvvm中的控制反转(IOC)

3
关于IOC,我读过以下定义和注册“interface”,但是我真的理解不了。
我们不需要自己的IOC容器,FreshMvvm内置了一个IOC容器。它使用TinyIOC作为底层,但使用不同的命名来避免冲突。
使用FreshIOC注册接口。如果你看到这段代码,在应用程序开始时执行此实现。
public App()  
{  
    InitializeComponent();  

    //Interface rgistration with FreshIOC  
    FreshIOC.Container.Register<IContactRepository, ContactRepository>();  
    FreshIOC.Container.Register<IValidator, ContactValidator>();  

    //var mainPage = FreshPageModelResolver.ResolvePageModel<AddContactPageModel>();  
    //MainPage = new FreshNavigationContainer(mainPage);  
} 

我们为什么需要注册接口?如果不注册,那么它的真实实现是什么?实施这个原则有什么优势吗?我正在参考这篇文章。

我正在尝试理解您对已提供答案、DI和IoC概念不理解的部分是什么?我想要了解需要解释的内容。 - Nkosi
我不明白我们为什么要这样做——“使用FreshIOC注册接口”,如果不注册接口,那么它是如何完成的?使用IOC有什么好处吗?所有这些问题都是出于理解而提出的。最近我开始涉足MVVM。你可能从你的理解角度观察到了这一点 :) 谢谢。 - R15
好的,我可以处理这个。 - Nkosi
快速问题,您是否已经理解了依赖倒置和依赖注入的概念? - Nkosi
很抱歉,我从未遇到过这个。 - R15
2个回答

4
如果你已经使用过Xamarin.Forms中的DependencySerices,你应该已经了解大部分内容了。从Xamarin.Forms的角度来解释。
假设你的ContentPage需要一个Network类来检查是否有网络连接,传统的做法是使用new关键字获取实例,这样你就可以调用它的方法。
public MyContentPage : ContentPage
{
    private Network network;
    public MyContentPage()
    {
        //..
        network = new Network();
    }
}

public Network()
{
    public bool HasConnectivity() { ... }
}

这没有任何问题,但是如果 Network 类需要一个内部的 Log 类呢?而且 MyContentPage 还需要 Log 类和 Dialog 类?而且这需要在你的其他50个页面中完成??依赖注入可以解决这些问题以及更多!

您创建接口及其实现,然后将它们注册到容器中。然后容器为您解析所有依赖项!

public MyContentPage : ContentPage
{
    private INetwork _network;
    private IDialog _dialog;
    public MyContentPage(INetwork network, IDialog dialog)
    {
        //..
        _network = network;
        _dialog = dialog;
    }
}    

public Network(ILog log)
{
    public bool HasConnectivity() { ... }
}

如果您已经注册了所有依赖项,容器将负责处理依赖关系图并为您解决它们。如果容器无法解决依赖关系图,可能是因为您没有注册或存在循环依赖关系,则会抛出异常。
这似乎起初完全不必要,但随着应用程序的增长,MVVM与DI相结合可以更加强大且易于开发。
我所解释的只是DI的一小部分,您可以在Martin Fowler的博客中阅读更多有关IoC和DI的内容。

最终,您似乎在MyContentPage构造函数中执行相同的操作,您使用new关键字执行了代码的第一部分。我的意思是,在第一个代码片段中,您编写了1行代码,在第二个代码片段中,您也正在编写1行代码,那么它有什么区别呢? - R15
这不是关于代码行数的问题!如果你想在所有50个页面中用ConsoleLog类替换Log类,你必须在所有页面中进行更改。但是通过依赖注入,您可以实现松耦合,只需将ILog注册到ConsoleLog即可!同样,您也可以轻松地对它们进行测试! - memsranga
2
@Arvindraja,正如Shan所说,Martin Fowler的文章对于理解“控制反转”和“依赖注入”非常有帮助。这只是一个过度简化的描述,但它可能有助于首先将IoC视为“没有类可以调用new OtherClass()”。现在...你为什么要编写这样的代码呢?这是另一个问题:)因此,您只需执行IocFramework.GiveMe<OtherClass>()而不是new OtherClass(),并让IoC找出该怎么做。然后,您再进一步,在自己的类构造函数中接受一个“OtherClass”。 - dss539
1
现在你会正确地问“为什么要费这个事情?!”... 因为它改变了谁来“掌控”构建和跟踪OtherClass对象。通过改变这个,您为测试打开了很多可能性,并且大大简化了代码库......除非它非常小。如果您只有像10个类,使用IoC框架并没有太大的优势。 - dss539
@Shan - 这只是更改类名,还有其他优点吗? - R15
@Arvindraja,这不仅仅是一个名称更改,你根据ILog接口改变了类的实现。如果ILog有writeToLog方法,Log类可能会将其写入文件,而ConsoleLog类可能只会写入调试控制台。只要实现了接口,你可以轻松地插入任何想要的实现,而无需付出任何努力。 - memsranga

3

内置的IOC容器是TinyIOC的一个抽象。

通过FreshMvvm抽象来在TinyIOC容器中注册类型:

FreshIOC.Container.Register<ISomeInterface, SomeImplementation>();

以后使用它:

// Gets object of type SomeImplementation
var instanceOfConcreteType = FreshIOC.Container.Resolve<ISomeInterface>();

这篇文章讨论了什么是IOC:什么是控制反转?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接