以编程方式确定代码是否在Silverlight中运行?

时间:2009-11-04 18:26:55

标签: c# .net silverlight

我有一个类需要在Silverlight和非Silverlight运行时运行。但是,行为略有不同,所以我需要像...这样的东西。

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

如何正确分配isRunningInSilverlight

3 个答案:

答案 0 :(得分:6)

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) { ... }
    ...
}

答案 1 :(得分:5)

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

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

您也可以使用ConditionalAttribute这种方法。

答案 2 :(得分:0)

使用预处理器指令的建议解决方案肯定会有效,但似乎更简单的解决方案是编写基类,然后从中派生Silverlight和非Silverlight版本。我认为维护和测试会更容易,更不用说提高整体代码的可读性。

看看基于运行时环境的语句是否像我使用Javascript进行编程的所有最糟糕的东西一样让我感到震惊,我讨厌的代码与我的项目无关,我不需要看到它。在那条道路上存在危险。