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

noc*_*ura 1 .net c# silverlight

我有一个类需要在Silverlight和非Silverlight运行时运行.然而,行为略有不同所以我需要像...

if(isRunningInSilverlight) {
  // do this
} else {
  // do that
}
Run Code Online (Sandbox Code Playgroud)

我该如何正确分配isRunningInSilverlight

joh*_*y g 6

杰夫的解决方案是直接的,并且会起作用.但是,如果你不喜欢#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; }
}
Run Code Online (Sandbox Code Playgroud)

与实现类似

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
    }
}
Run Code Online (Sandbox Code Playgroud)

在你的消费者

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
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

现在您可以独立于实际运行时进行测试

// 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 ();
}
Run Code Online (Sandbox Code Playgroud)

现在在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) { ... }
    ...
}
Run Code Online (Sandbox Code Playgroud)


Jef*_*tes 5

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

#if SILVERLIGHT
// Do silverlight stuff
#else
// Do other stuff
#endif
Run Code Online (Sandbox Code Playgroud)

你也可以使用ConditionalAttribute这种方法.