Jeff's solution is direct and will work. However, if you are adverse to #if
compiler directives popping up all over your code, you can centralize and abstract it all away with a little interface magic.
Consider the following,
// 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; }
}
with an implementation like
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
}
}
in your consumers
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
}
}
}
and now you can test independent of the actual runtime
// 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 ();
}
and now in prod, you can use a container, factory, or default constructor of your choice, to ensure concrete implementation is passed. For example, revisiting MyClass snippet from above,
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) { ... }
...
}