在继续之前,尽管我以前使用过 caliburn,但我对 Prism 的经验很少,所以我假设它以类似的方式工作。但我确实对 nsubstitute 有一点经验。
将替代品用于设计目的是不是一个坏主意?
我的简短回答是否定的。
这并不完全理想,但是当您有一个设计部门(或在您继续编码时负责 UI 元素的人)时,将 UI 执行的代码与设计过程隔离开来是一种很好的做法,因为您将能够改进您的界面即使要实时执行的代码有问题。
当我说替代品时,我指的是由 Visual Studio 或 Blend 在设计时创建的真实(样本数据等)实例。(我将在最后提供一个样本)。
模拟这些元素是个坏主意吗?
也许不是,尽管您将在项目中包含更多对执行并不那么重要的依赖项。
它的积极方面是:
模拟定义意味着您将维护更少的代码,但您将无法在这些假实例上模拟数据(或者除非您开始为每个模拟返回样本数据)。
不利的一面:
首先,根据模拟框架,您将加载(在设计时)动态创建的代理或假货实例,以模拟某些行为拦截调用和其他内容。如果您创建大量不如实际代码轻量级的对象,这可能是一个痛苦的操作。
除了你的设计师(如果有一个混合大师)必须收集关于地狱 nsubstitute(或你喜欢的模拟框架)如何工作的知识。
如果我有一个设计师帽,并且您向我展示了一个具有特定定义的类,我可以复制该类与使用名为替代品的外部库定义的类,我可能会告诉您我更喜欢第一个选项,因为我不需要学习其他任何东西除了一点 c#。即使这样,我也不会尝试触及该代码。
将 nsubstitute 添加到您的项目有什么缺点吗?
只要您正确使用 DesignInstance 并且对带有模拟的代码的引用与实际功能隔离,并且您不尝试替换非虚拟属性或具有多个参数或密封类的实例(基本上 nsubstitute 对要替换的内容的任何限制)替代)你会没事的,因为设计属性将在你的代码的特殊模式下执行。
特别是 NSubstitute 可能会在尝试创建实例或访问某些属性时抛出异常,在这种情况下,IDE可能会在加载时崩溃或崩溃控件。
有样品吗?
你可能知道要写什么,但它就在这里(虽然不是棱镜)。
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/winfx/expression/blend/2008"
xmlns:vm="clr-namespace:Project.Namespace.ViewModels.DataSamples"
d:DataContext="{d:DesignInstance IsDesignTimeCreatable=True, Type={x:Type NationViewModelSampleData}}">
<StackPanel DataContext="{Binding Leader}">
<TextBlock Text="{Binding FirstName}" />
<TextBlock Text="{Binding LastName}" />
</StackPanel>
</UserControl>
NationViewModel 在哪里实现了这样的接口
namespace Project.Namespace.ViewModels
{
public interface INationViewModel
{
IPerson Leader { get; }
IEnumerable<IPerson> Citizens { get; }
}
public interface IPerson
{
string FirstName { get; }
string LastName { get; }
}
}
样本数据为:
namespace Project.Namespace.ViewModels.DataSamples
{
public class NationViewModelSampleData : Project.Namespace.ViewModels.INationViewModel
{
public NationViewModelSampleData()
{
// You could have done something like this as well, but for this sample was more code to write.
// Leader = Substitute.For<IPerson>();
// Leader.FirstName.Returns("John");
// Leader.LastName.Returns("Doe");
// or just...
Leader = new Person { FirstName = "John", LastName = "Doe" };
Citizens = new IPerson[]
{
new Person { FirstName = "Malcolm", LastName = "Little" },
Leader
};
// You could have applied the mock to this section as well... again, more code for this scenario than just a simple real instance.
}
public IPerson Leader { get; private set; }
public IEnumerable<IPerson> Citizens { get; private set; }
}
}
在这个示例中,我决定使用实际实例,因为我想象的 Person 实现非常小并且使用安全......但我希望它会变得越来越复杂如您之前所述,实例或模拟它。
希望这个评论有帮助。
干杯!