Reputation: 13121
I have a class that needs to run in both Silverlight and non-Silverlight runtimes. However, the behavior is slightly different so I need something like...
if(isRunningInSilverlight) {
// do this
} else {
// do that
}
How do I correctly assign isRunningInSilverlight
?
Upvotes: 1
Views: 2243
Reputation: 1444
The suggested solutions that use pre-processor directives will certainly work, but it seems like a simpler solution would be to just write a base class and then derive both a Silverlight and a non-Silverlight version from it. I would think it would be much easier to maintain and test that way, not to mention enhancing readability of your code overall.
Seeing if statements based on runtime environments strikes me like all of the worst stuff about programming with Javascript and I hate having code that isn't relevent to my project mucking about where I don't need to see it. On that path lies danger.
Upvotes: 0
Reputation: 3561
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) { ... }
...
}
Upvotes: 6
Reputation: 62377
Considering that different compilers are used to create Silverlight and non-Silverlight assemblies, you could use compiler directives and conditionally compile your code rather than detect the difference at runtime. Just define SILVERLIGHT
(or some other define) for the Silverlight build and then have:
#if SILVERLIGHT
// Do silverlight stuff
#else
// Do other stuff
#endif
You could use the ConditionalAttribute
as well with this approach.
Upvotes: 5