MvvmCross和PCL服务层 - 如何使用OS特定功能

时间:2017-10-31 12:31:08

标签: c# xamarin mvvmcross

谷歌搜索了一段时间,但没有发现真的很好。

所以,问题是,在MVVM Cross指南中,我们的解决方案(针对移动平台)被分开,例如,HelloWorld.Core项目和几个特定于平台的项目,例如HelloWorld.Android.UI

您可以在此处查看完整教程https://www.mvvmcross.com/documentation/tipcalc-tutorial/the-tip-calc-tutorial

而且,问题是,在我们创建服务的.Core项目中,ViewModel和我们在MVVM Cross中注册它提供了IoC容器。

在MvvmCross文档Service提供的示例中,实现非常简单,只需要一个函数

    public class CalculationService: ICalculationService
    {
        public double TipAmount(double subTotal, int generosity)
        {
            return subTotal * ((double)generosity)/100.0;
        }
    }

所以我们继续,在我们的App.cs中注册,然后将其用于绑定的ViewModel

public class App: MvxApplication
    {
        public App()
        {
            Mvx.RegisterType<ICalculationService, CalculationService>();
            Mvx.RegisterSingleton<IMvxAppStart>(new MvxAppStart<HomeViewModel>());
        }
    }

查看型号代码:

public class TipViewModel : MvxViewModel
    {
        readonly ICalculation _calculation;

        public TipViewModel(ICalculation calculation)
        {
            _calculation = calculation;
        }

    // ...

        double _tip;

        public double Tip
        {
            get {
                return _tip;
            }
            set
            {
                _tip = value;
                RaisePropertyChanged(() => Tip);
            }
        }

        void Recalculate()
        {
            Tip = _calculation.TipAmount(SubTotal, Generosity);
        }
    }

但问题是,当我开始玩这个时,我决定,比方说,编写一些简单的本地存储数据扫描程序来查找一些特定的文件。

简单的代码示例:

 public class SimpleDataScanner : IBaseDataScanner
    {
        private string _basePath { get; set; }

        private List<string> _scanResult { get; set; }

        public SimpleDataScanner()
        {
            _basePath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal);
            _scanResult = new List<string>();
        }

        public List<string> BasicDataScan(string startPath = null)
        {
            string startFolder = _basePath;

            if (startPath.Length > 0 && startPath.Length != null)
            {
                startFolder = Path.Combine(_basePath, startPath);
            }

            try
            {
                TreeScan(startFolder);
            }
            catch (Exception)
            {

                throw;
            }

            return _scanResult;

        }

        private void TreeScan(string path)
        {
            foreach (var file in Directory.GetFiles(path))
            {
                if (Path.HasExtension("pdf"))
                {
                    _scanResult.Add(file);
                }
            }
            foreach (string dir in Directory.GetDirectories(path))
            {
                TreeScan(dir);
            }
        }
    }

而且,正如我发现的那样,问题是:

1)我无法在PCL中使用Android特定的功能和属性

2)我不能在我的PCL Core项目中使用引用,比方说,其他一些Android类lib项目

因此,我无法创建有效的服务,这意味着我无法在IoC-container中注册它并传递给ViewModel。

做这种事的方式是什么? 任何教程?或者说我的想法错了?

1 个答案:

答案 0 :(得分:3)

您需要在平台代码中实现该接口,并在平台项目内Setup.cs中的接口上注册具体实现。因此,在您的情况下,IDataScanner项目中会存在Core,而SimpleDataScanner会存在于Android项目中。

Setup.cs内,您将注册具体实现,如下所示:

protected override void InitializeFirstChance()
{
    base.InitializeFirstChance();

    Mvx.RegisterSingleton<IDataScanner>(() => new SimpleDataScanner());
}

基本上,如果接口需要实现特定于平台或完整的.NET框架代码,那么每个平台实现都存在于平台中并在平台设置中注册。如果在Core项目中共享接口和实现,则可以在App.cs中注册依赖项。