【问题标题】:Mark code to not run at design-time将代码标记为不在设计时运行
【发布时间】:2014-09-16 04:28:06
【问题描述】:

使用新的 Xamarin.iOS 设计器时,它将自动创建您的控制器、视图等,以便您的 C# 代码运行并实际呈现在设计图面上(而不必等到运行时)。

所以如果你有一个控制器,它的构造函数和ViewDidLoad 将被调用。

假设我有一个这样的控制器:

class MyController
{
    readonly ISomeService service;

    public MyController(IntPtr handle) : base(handle)
    {
        service = MyIoCContainer.Get<ISomeService>();
    }
}

显然在设计时,IoC 容器将完全为空并引发异常。

有没有办法用 Xamarin.iOS 设计器解决这个问题?也许#if !DESIGN_TIME 或类似的东西?或者有没有办法让我的 IoC 容器在设计时返回所有对象的模拟实例?

【问题讨论】:

    标签: c# ios xamarin.ios xamarin


    【解决方案1】:

    目前推荐的方法是让您的类实现 IComponent 接口。请参阅this doc 了解更多信息。所以你的 MyController 类可能看起来像这样:

    [Register ("MyController")]
    class MyController : UIViewController, IComponent
    {
        #region IComponent implementation
    
        public ISite Site { get; set; }
        public event EventHandler Disposed;
    
        #endregion
    
        readonly ISomeService service;
    
        public MyController(IntPtr handle) : base(handle)
        {
        }
    
        public override void AwakeFromNib ()
        {
            if (Site == null || !Site.DesignMode)
                service = MyIoCContainer.Get<ISomeService>();
        }
    }
    

    请注意,Site 在构造函数中始终为null。从故事板初始化的首选位置是AwakeFromNib 方法。我更新了代码示例以反映这一点。

    【讨论】:

      【解决方案2】:

      周末我有一个非常相似的问题;在查看设计器中的视图控制器时,我想要一种快速简便的方法来防止从 ViewDidLoad 进行 API 调用。

      这是我为处理它而创建的快速简便的检查。 (取自https://stackoverflow.com/a/25835680/841832

      Studio Storyboard 设计器不会调用 AppDelegate 事件,因此您可以利用它来创建检查。

      AppDelegate.cs

      public partial class AppDelegate: UIApplicationDelegate
      {
          public static bool IsInDesignerView = true;
      
          public override bool FinishedLaunching(UIApplication app, NSDictionary options)
          {
              IsInDesignerView = false;
      
              return true;
          }
      }
      

      视图控制器

      public class MyController: UIViewController
      {
          readonly ISomeService service;
      
          public MyController(IntPtr handle) : base(handle)
          {
              service = AppDelegate.IsInDesignerView ?
                  new Moq<ISomeService>() :
                  MyIoCContainer.Get<ISomeService>();
          }
      }
      

      【讨论】:

      • 我认为你的方法也有效,但我认为@chkn 的方法是首选。他们遵循老设计师的相同模式,例如 WinForms。不过,您的可能更简单。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-12-28
      • 1970-01-01
      • 2016-05-03
      • 2017-07-09
      相关资源
      最近更新 更多