MonoDroid 和 MonoTouch 的共享库

Posted

技术标签:

【中文标题】MonoDroid 和 MonoTouch 的共享库【英文标题】:Shared library for MonoDroid and MonoTouch 【发布时间】:2012-12-13 06:53:17 【问题描述】:

所以我的公司完全来自一个 C# .Net 环境,所以我们自然而然地将 Mono 用于移动开发。我们有一个非常广泛的 Windows 平台库,我可以将其中的大部分移植为 android 类库。这个想法是这个 Android 类库将成为我们的移动平台库,将来可以为 MonoTouch 重用(尚未测试,但只要没有 Android 特定代码,MonoTouch 项目就可以引用 Android 类库)。不过,在库中,有很多日志语句,对于 windows 环境,这些语句最终只是跟踪语句(包装在自定义帮助程序类中)。我们希望保留日志记录语句并基于当前环境(ios 或 Android),只需将它们转换为原生日志记录即可。

我计划在移动平台库中使用部分声明进行日志记录,并让 Android 和 iOS 特定库包含这些部分日志记录方法的实现。但是当我意识到部分在程序集之间不起作用时,这一切都崩溃了。

所以现在我不知道该怎么做。如果有两个独立的 iOS 和 Android 平台库并链接相同的文件,我唯一能想到的。 (Xamarin 可能有一个日志类可以做到这一点,但我们仍然需要为未来的任何其他抽象提出一个模式)

感谢任何建议。我们仍处于实验/计划阶段,因此我们可能会忽略某些内容,如果是这种情况,请告诉我们。

谢谢。

编辑 假设我有以下简单的静态类。

public static class TraceHelper

    public static void WriteLine(string message)
    
        // Validation and preprocessing
        Trace.WriteLine(message);
    

我在移动平台库中有数百次调用此方法。现在假设我在我的 Android 应用程序中引用了这个库,有没有办法在不修改库本身的情况下覆盖 TraceHelper.WriteLine() 的实现?

更新 我们最终创建了实现缺失的 .NET 功能的 Android 和 iOS 库。只需将本机等效功能包装在相同的 .NET 命名空间和类中。例如:

using Android.Util;

namespace System.Diagnostics

    public static class Trace
    
        #region Non-Public Data Members

        private const string Tag = "Trace";

        #endregion

        public static void WriteLine(string message)
        
            Log.WriteLine(LogPriority.Verbose, Tag, message);
        
    

【问题讨论】:

不确定我是否可以提供具体建议,因为您不想更改日志记录语句。在我的公司中,我们也在 Windows/Silverlight/Android/Unity3D 之间共享代码,但是我们使用可重用接口抽象了我们的日志实现。作为应用程序引导的一部分,我们在后台附加了一个特定于平台的记录器。因此,我们所有访问记录器的代码都会通过静态工厂访问可重用的ILog 接口,并且不知道所使用的平台细节。 (也有助于根据需要在同一平台内附加不同的记录器) (续)当然,这可能意味着您必须更改从业务逻辑中记录的方式。也许您应该发布一个代码示例,说明您的业务/UI 层当前如何记录以及您愿意在多大程度上(如果有)进行更改。 Chris - 100% 同意你的 cmets - 你应该把它写成答案。 【参考方案1】:

在 mvvmcross 中,我使用接口解决了这个问题。

我已经声明了一个通用的 IMvxTrace 接口,然后我添加了它的单例实现,例如:

https://github.com/slodge/MvvmCross/blob/master/Cirrious/Cirrious.MvvmCross/Platform/Diagnostics/MvxTrace.cs

此单例使用底层 _realTrace 实现。

在机器人上,_realTrace 是:

https://github.com/slodge/MvvmCross/blob/master/Cirrious/Cirrious.MvvmCross/Android/Platform/MvxDebugTrace.cs

在触摸时,_realTrace 是:

https://github.com/slodge/MvvmCross/blob/master/Cirrious/Cirrious.MvvmCross/Touch/Platform/MvxDebugTrace.cs

在wpf、win8和wp上同样有自定义实现

我已经使用文件链接(在主文件中)完成了这项工作,但最近使用了 PCL 和特定于平台的库的混合。我的个人偏好是 PCL,因为我喜欢使用重构工具 - 与使用 #if 代码相比,这些对 PCL 的效果要好得多。此外,随着我​​的代码从 1 个平台增加到 6 个平台,我发现 6 组 #if 语句太复杂而无法维护。

请注意,上面的代码还使用了依赖注入和 IOC 技术。我发现这对跨平台代码共享非常有帮助。有几个可移植的 IOC 库可用,包括 tinyioc、xplatutils、opennetcf 和 mvvmcross 的简单 IOC。

【讨论】:

【参考方案2】:

解决此问题的最简单方法是设置一个 iOS 项目,您基本上可以这样做:

public static class TraceHelper

    public static void WriteLine(string message)
    
#if MONOTOUCH
        Console.WriteLine(message);//or something else
#else
        Trace.WriteLine(message);
#endif
    

您将创建一个 MonoTouch 类库项目,并“链接”原始 Mono for Android 项目中的所有文件。然后,如果需要,您可以设置 MONOTOUCH 编译器标志以具有特定的 iOS 或 Android 代码。

我们一直采用这种方法,并且有时更喜欢它而不是使用 PCL(可移植类库),因为它具有灵活性。

【讨论】:

如果我添加了 Android 和 iOS 特定的代码,那是不是意味着我不能在任何一个项目中引用这个库?在它们之间拥有两个库(iOS 和 Android)和“链接”文件似乎不太理想。谢谢。 如果您有任何特定于平台的代码,您将不得不在某种程度上这样做。使用 PCL 是一个好主意(就像 Stuart 建议的那样),但您仍然需要在每个平台上存根接口。

以上是关于MonoDroid 和 MonoTouch 的共享库的主要内容,如果未能解决你的问题,请参考以下文章

在 monotouch/monodroid 中使用 mocks 进行单元测试

使 PCL Xamarin (MonoDroid/MonoTouch) 兼容的问题

使用 MonoTouch 反序列化 Protobuf 文件的问题

Monodroid 和 adMob 插页式广告

Monodroid 和 adMob 插页式广告

monotouch 中的自定义 uitabbar,类似于语音备忘录应用程序