代码之家  ›  专栏  ›  技术社区  ›  noctonura

确定代码是否在Silverlight中运行的编程方法?

  •  1
  • noctonura  · 技术社区  · 16 年前

    我有一个类需要在Silverlight和非Silverlight运行时运行。但是,行为有点不同,所以我需要像…

    if(isRunningInSilverlight) {
      // do this
    } else {
      // do that
    }
    

    如何正确分配 isRunningInSilverlight ?

    3 回复  |  直到 16 年前
        1
  •  5
  •   Jeff Yates    16 年前

    考虑到不同的编译器用于创建Silverlight和非Silverlight程序集,您可以使用编译器指令并有条件地编译代码,而不是在运行时检测差异。只是定义 SILVERLIGHT (或其他一些定义)对于Silverlight生成,然后具有:

    #if SILVERLIGHT
    // Do silverlight stuff
    #else
    // Do other stuff
    #endif
    

    你可以用 ConditionalAttribute 以及这种方法。

        2
  •  6
  •   Community CDub    8 年前

    Jeff's solution 是直接的,而且会工作。但是,如果你对 #if 编译器指令出现在你的代码中,你可以用一点界面魔术来集中和抽象它。

    考虑以下内容:

    // a nice neat public interface to centralize all of your 
    // run time requirements
    public interface IRuntimeInfo
    {
        // true if silverlight runtime, false if full-Clr
        bool IsSilverlight { get; }
    }
    

    使用类似的实现

    public class RuntimeInfo : IRuntimeInfo
    {
        public bool IsSilverlight { get; private set; }
        public RuntimeInfo ()
        {
            // @Jeff's compiler directives - er, taking his
            // word 'SILVERLIGHT' is actually defined
            #if SILVERLIGHT
                IsSilverlight = true;
            #else
                IsSilverlight = false;
            #endif
        }
    }
    

    在你的消费者中

    public class MyClass
    {
        private readonly IRuntimeInfo _runtimeInfo = null;
        public MyClass (IRuntimeInfo runtimeInfo)
        {
            _runtimeInfo = runtimeInfo;
        }
        public void SomeMethod ()
        {
            if (_runtimeInfo.IsSilverlight)
            {
                // do your thang
            }
            else
            {
                // do some other thang
            }
        }
    }
    

    现在你可以独立于 实际的 运行时

    // testing silverlight behaviour of MyClass under full CLR
    [TestMethod]
    public void Test_SilverlightBehaviour ()
    {
        // setup mock, using Moq below
        Mock<IRuntimeInfo> _mockRuntimeInfo = new Mock<IRuntimeInfo> ();
        _mockRuntimeInfo.Setup (r => r.IsSilverlight).Returns (true);
        // pass mock to consumer
        MyClass myClass = new MyClass (_mockRuntimeInfo);
        // test silverlight-specific behaviour
        myClass.SomeMethod ();
    }
    
    // testing CLR behaviour of MyClass under full CLR
    [TestMethod]
    public void Test_FullClrBehaviour ()
    {
        // setup mock, using Moq below
        Mock<IRuntimeInfo> _mockRuntimeInfo = new Mock<IRuntimeInfo> ();
        _mockRuntimeInfo.Setup (r => r.IsSilverlight).Returns (false);
        // pass mock to consumer
        MyClass myClass = new MyClass (_mockRuntimeInfo);
        // test full-Clr-specific behaviour
        myClass.SomeMethod ();
    }
    

    现在在prod中,您可以使用自己选择的容器、工厂或默认构造函数,以确保传递具体的实现。例如,从上面重新访问myclass片段,

    public class MyClass
    {
        // default constructor. personally, I would opt to use a container
        // like Castle Windsor Container, or Microsoft's Unity, but if you
        // have no control over application or it's just this "one" thing,
        // just default to a concrete implementation below.
        public MyClass () : this (new RuntimeInfo ()) { }
        // what we call an "injector" constructor, because runtime info is
        // passed - or "injected" - into instance.
        public MyClass (IRuntimeInfo runtimeInfo) { ... }
        ...
    }
    
        3
  •  0
  •   Raumornie    16 年前

    使用预处理器指令的建议解决方案当然可以工作,但似乎更简单的解决方案是编写一个基类,然后从中派生Silverlight和非Silverlight版本。我认为这样维护和测试会容易得多,更不用说提高代码的可读性了。

    看看基于运行时环境的语句是否像用javascript编程的所有最糟糕的东西一样打动了我,我讨厌有与我的项目无关的代码在我不需要看到它的地方胡闹。在那条路上有危险。