c# – 是否可以在数据对象中使用Code Contracts的不变量?
这个问题直接来自
Validating parameters properties with Code Contracts.
在该问题中,Ahmed KRAIEM和Stephen J. Anderson都声明,如果必须始终保持与对象的状态正确性相关的检查,则应将其置于该对象内. 但是我遇到了一个实现它的问题:在将检查实现为Code Contracts的不变量之后,我不再能够使用对象初始化,AutoMapper或EntityFramework. 出现问题的原因是它们首先使用默认的空构造函数创建一个新对象,然后填充各种属性,这会触发Code Contracts的不变量,从而在运行时生成异常. 一个快速示例包含在Visual Studio单元测试中(您需要通过NuGet添加AutoMapper才能使其工作): namespace Playground.Sandbox { using System.Diagnostics.Contracts; using AutoMapper; using Microsoft.VisualStudio.TestTools.UnitTesting; [TestClass] public class ContractTest { private const int CatAge = 5; private const string CatName = "Tama"; private const int DogAge = 10; private const string DogName = "Poochi"; static ContractTest() { Mapper.CreateMap<Dog,Cat>(); } [TestMethod] public void EmptyConstructorShouldThrow() { var cat = new Cat(); Assert.AreEqual(default(int),cat.Age); Assert.AreEqual(default(string),cat.Name); } [TestMethod] public void NonEmptyConstructorShouldNotThrow() { var cat = new Cat(CatAge,CatName,true); Assert.AreEqual(CatAge,cat.Age); Assert.AreEqual(CatName,cat.Name); } [TestMethod] public void ObjectInitializerShouldThrow() { var cat = new Cat { Age = CatAge,Name = CatName }; Assert.AreEqual(CatAge,cat.Name); } [TestMethod] public void AutoMapperConversionShouldThrow() { var dog = new Dog { Age = DogAge,Name = DogName }; var cat = Mapper.Map<Dog,Cat>(dog); Assert.AreEqual(DogAge,cat.Age); Assert.AreEqual(DogName,cat.Name); } private class Cat { public Cat() { } public Cat(int age,string name,bool doesMeow) { this.Age = age; this.Name = name; } public int Age { get; set; } public string Name { get; set; } [ContractInvariantMethod] private void ObjectInvariant() { Contract.Invariant(this.Age > 0); Contract.Invariant(!string.IsNullOrWhiteSpace(this.Name)); } } private class Dog { public int Age { get; set; } public string Name { get; set; } } } } 如果你想知道为什么有公共的Cat(int,string,bool)构造函数,如果没有使用它,就是愚弄AutoMapper.对于此示例,我需要一个构造函数来初始化整个对象,AutoMapper会识别它并自动使用它来初始化目标对象.但是,我们的数据对象没有这样的构造函数(而且,它们不能,因为它们可以具有许多属性). 唯一通过的测试是NonEmptyConstructorShouldNotThrow,其他都是(正确)失败. 出现问题的原因是它们首先使用默认的空构造函数创建一个新对象,从而在运行时生成异常. 我是否错误地使用了Code Contracts,或者在使用对象初始化,AutoMapper或EntityFramework时无法在数据对象中实现不变量? 解决方法
在Cat的默认构造函数中设置有效值,如下所示:
public Cat() { Age = 1; Name = "Cat"; } 一切都会好的. 编辑: 因此,您必须为Age和Name设置有效值! 否则,默认构造函数完全没有任何意义,即使您计划,甚至更多甚至您承诺在以后设置属性. 唯一的另一种方法是让你的类可构建,意味着你调用一个完成初始化的方法,然后激活并使用你的合同检查方法. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |