noctonura
noctonura

Reputation: 13121

Programmatic way to determine if code is running in Silverlight?

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

Answers (3)

Raumornie
Raumornie

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

johnny g
johnny g

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

Jeff Yates
Jeff Yates

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

Related Questions