我有一个类需要在Silverlight和非Silverlight运行时运行。但是,行为略有不同,所以我需要像...这样的东西。
if(isRunningInSilverlight) {
// do this
} else {
// do that
}
如何正确分配isRunningInSilverlight
?
答案 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进行编程的所有最糟糕的东西一样让我感到震惊,我讨厌的代码与我的项目无关,我不需要看到它。在那条道路上存在危险。