The type or namespace name ‘EventSourceCreatedEventArgs’ does not exist in the namespace ‘System.Diagnostics.Tracing’ (are you missing an assembly reference?) 上網查了一下找到以下解法
public void 取得現在時間()
{
using (ShimsContext.Create())
{
System.Fakes.ShimDateTime.NowGet= () =>
{
return new DateTime(2016, 9, 25);
};
//arrange
var expected = new DateTime(2016, 9, 25);
//act
var actual = DateTime.Now;
//assert
Assert.AreEqual(expected, actual);
}
}
```
補充2017/01/24
單元測試Fake的功能,以Visual Studio 2015來說只有Enterprise版本才有支援,所以使用的時候請特別小心,像今天公司因為授權費的關係,要求調降成Professional,之前有用到Fake的地方就都測不過了,還請特別注意
3. 驗證的地方改成如下 ```csharp var Parameter = new APIInputParameter { ID = "123", Name = "Toyo" }; // 檢查輸入參數 var validator = new APIInputParameterValidator();
var error = validator.Validate(Parameter).Errors.FirstOrDefault(); if (error.HasError()) { string.Format("{0}-{1}",error.ErrorCode,error.ErrorMessage).Dump(); } else { "驗證成功".Dump(); }
///<summary> /// Initializes a new instance of the <see cref="DateTimeValidator"/> class. ///</summary> ///<param name="allowEmpty">if set to <c>true</c> [allow empty].</param> publicDateTimeValidator(bool allowEmpty) : base("型別錯誤") { this.AllowEmpty = allowEmpty; }
///<summary> /// Returns true if ... is valid. ///</summary> ///<param name="context">The context.</param> ///<returns> ///<c>true</c> if the specified context is valid; otherwise, <c>false</c>. ///</returns> protectedoverrideboolIsValid(PropertyValidatorContext context) { var propertyValue = context.PropertyValue asstring;
if (this.AllowEmpty && string.IsNullOrWhiteSpace(propertyValue)) { returntrue; }
intvalue; bool result = int.TryParse(propertyValue, outvalue); //TimeStamp if (result && value > 0) { returntrue; }
DateTime dateTimeValue; return DateTime.TryParse(propertyValue, out dateTimeValue); } }
擴充方法```csharp /// /// 是 DateTime 型別 or TimeStamp . /// /// /// The type of the t property. /// The rule builder. /// IRuleBuilderOptions<T, TProperty>. public static IRuleBuilderOptions<T, TProperty> IsDateTimeOrTimeStamp<T, TProperty>( this IRuleBuilder<T, TProperty> ruleBuilder) { return ruleBuilder.SetValidator(new DateTimeValidator(allowEmpty: false)); }
/// <summary>
/// 是 DateTime 型別 or TimeStamp, 但允許 String.Empty.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="TProperty">The type of the t property.</typeparam>
/// <param name="ruleBuilder">The rule builder.</param>
/// <returns>IRuleBuilderOptions<T, TProperty>.</returns>
public static IRuleBuilderOptions<T, TProperty> IsDateTimeOrTimeStampAllowEmpty<T, TProperty>(
this IRuleBuilder<T, TProperty> ruleBuilder)
{
return ruleBuilder.SetValidator(new DateTimeValidator(allowEmpty: true));
}
/// <summary> /// Initializes a new instance of the <see cref="GUIDArrayValidator"/> class. /// </summary> /// <param name="allowEmpty">if set to <c>true</c> [allow empty].</param> public GUIDArrayValidator( bool allowEmpty = false) :base("傳入參數錯誤。") { this.AllowEmpty = allowEmpty; }
/// <summary> /// Returns true if ... is valid. /// </summary> /// <param name="context">The context.</param> /// <returns> /// <c>true</c> if the specified context is valid; otherwise, <c>false</c>. /// </returns> protected override bool IsValid(PropertyValidatorContext context) { var propertyValue = context.PropertyValue as List<string>; if (AllowEmpty && (propertyValue == null || propertyValue.Count == 0)) { return true; }
Guid guid; foreach (var item in propertyValue) { if (!Guid.TryParse(item, out guid)) { return false; } }
return true; } }
擴充方法```csharp /// /// 是 Guid Array, 但允許空集合. /// /// /// The type of the t property. /// The rule builder. /// IRuleBuilderOptions<T, TProperty>. public static IRuleBuilderOptions<T, TProperty> IsGUIDArrayAllowEmpty<T, TProperty>( this IRuleBuilder<T, TProperty> ruleBuilder) { return ruleBuilder.SetValidator(new GUIDArrayValidator(allowEmpty: true)); }
/// <summary>
/// 是 Guid Array.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="TProperty">The type of the t property.</typeparam>
/// <param name="ruleBuilder">The rule builder.</param>
/// <returns>IRuleBuilderOptions<T, TProperty>.</returns>
public static IRuleBuilderOptions<T, TProperty> IsGUIDArray<T, TProperty>(
this IRuleBuilder<T, TProperty> ruleBuilder)
{
return ruleBuilder.SetValidator(new GUIDArrayValidator(allowEmpty: false));
}
/// <summary> /// Initializes a new instance of the <see cref="IntegerValidator"/> class. /// </summary> /// <param name="allowEmpty">if set to <c>true</c> [allow empty].</param> public IntegerValidator(bool allowEmpty = false) : base("型別錯誤") { this.AllowEmpty = allowEmpty; }
/// <summary> /// Returns true if ... is valid. /// </summary> /// <param name="context">The context.</param> /// <returns> /// <c>true</c> if the specified context is valid; otherwise, <c>false</c>. /// </returns> /// <exception cref="NotImplementedException"></exception> protected override bool IsValid(PropertyValidatorContext context) { var propertyValue = context.PropertyValue as string;
if (this.AllowEmpty && string.IsNullOrWhiteSpace(propertyValue)) { return true; }
int value; bool result = int.TryParse(propertyValue, out value); return result; } }
擴充方法```csharp /// /// 是 Integer 型別. /// /// /// The type of the t property. /// The rule builder. /// IRuleBuilderOptions<T, TProperty>. public static IRuleBuilderOptions<T, TProperty> IsInteger<T, TProperty>( this IRuleBuilder<T, TProperty> ruleBuilder) { return ruleBuilder.SetValidator(new IntegerValidator(allowEmpty: false)); }
/// <summary>
/// 是 Integer 型別, 但允許 String.Empty.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="TProperty">The type of the t property.</typeparam>
/// <param name="ruleBuilder">The rule builder.</param>
/// <returns>IRuleBuilderOptions<T, TProperty>.</returns>
public static IRuleBuilderOptions<T, TProperty> IsIntegerAllowEmpty<T, TProperty>(
this IRuleBuilder<T, TProperty> ruleBuilder)
{
return ruleBuilder.SetValidator(new IntegerValidator(allowEmpty: true));
}
擴充方法```csharp /// /// 符合數字區間,但允許空值. /// EX : (1 < x < 3) /// /// /// The type of the property. /// The type of the numeric. /// The rule builder. /// Up threshold. /// Down threshold. /// public static IRuleBuilderOptions<T, TProperty> IsNumericAllowEmptyOrBetweenOf<T, TProperty, TNumeric>( this IRuleBuilder<T, TProperty> ruleBuilder, string upThreshold, string downThreshold) where TNumeric : IComparable { return ruleBuilder.SetValidator( new NumericBetweenInValidator( upThreshold, downThreshold, allowEquals: false, allowEmpty: true)); }
/// <summary>
/// 符合數字區間且允許等於閥值,但允許空值.
/// <para>EX : (1 <= x <= 3) </para>
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="TProperty">The type of the property.</typeparam>
/// <typeparam name="TNumeric">The type of the numeric.</typeparam>
/// <param name="ruleBuilder">The rule builder.</param>
/// <param name="upThreshold">Up threshold.</param>
/// <param name="downThreshold">Down threshold.</param>
/// <returns></returns>
public static IRuleBuilderOptions<T, TProperty> IsNumericAllowEmptyOrBetweenOfAllowEquals<T, TProperty, TNumeric>(
this IRuleBuilder<T, TProperty> ruleBuilder,
string upThreshold,
string downThreshold)
where TNumeric : IComparable
{
return ruleBuilder.SetValidator(
new NumericBetweenInValidator<TNumeric>(
upThreshold,
downThreshold,
allowEquals: true,
allowEmpty: true));
}
/// <summary>
/// 符合數字區間.
/// <para>EX : (1 < x < 3) </para>
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="TProperty">The type of the property.</typeparam>
/// <typeparam name="TNumeric">The type of the numeric.</typeparam>
/// <param name="ruleBuilder">The rule builder.</param>
/// <param name="upThreshold">Up threshold.</param>
/// <param name="downThreshold">Down threshold.</param>
/// <returns></returns>
public static IRuleBuilderOptions<T, TProperty> IsNumericBetweenOf<T, TProperty, TNumeric>(
this IRuleBuilder<T, TProperty> ruleBuilder,
string upThreshold,
string downThreshold)
where TNumeric : IComparable
{
return ruleBuilder.SetValidator(
new NumericBetweenInValidator<TNumeric>(
upThreshold,
downThreshold,
allowEquals: false,
allowEmpty: false));
}
/// <summary>
/// 符合數字區間且允許等於閥值
/// <para>EX : (1 <= x <= 3) </para>
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="TProperty">The type of the property.</typeparam>
/// <typeparam name="TNumeric">The type of the numeric.</typeparam>
/// <param name="ruleBuilder">The rule builder.</param>
/// <param name="upThreshold">Up threshold.</param>
/// <param name="downThreshold">Down threshold.</param>
/// <returns></returns>
public static IRuleBuilderOptions<T, TProperty> IsNumericBetweenOfAllowEquals<T, TProperty, TNumeric>(
this IRuleBuilder<T, TProperty> ruleBuilder,
string upThreshold,
string downThreshold)
where TNumeric : IComparable
{
return ruleBuilder.SetValidator(
new NumericBetweenInValidator<TNumeric>(
upThreshold,
downThreshold,
allowEquals: true,
allowEmpty: false));
}
///<summary> /// Initializes a new instance of the <see cref="NumericArrayValidator{TNumeric}"/> class. ///</summary> ///<param name="allowEmpty">if set to <c>true</c> [allow empty].</param> publicNumericArrayValidator(bool allowEmpty) : base("型別錯誤") { this.AllowEmpty = allowEmpty; }
///<summary> /// Returns true if ... is valid. ///</summary> ///<param name="context">The context.</param> ///<returns> ///<c>true</c> if the specified context is valid; otherwise, <c>false</c>. ///</returns> protectedoverrideboolIsValid(PropertyValidatorContext context) { var propertyValue = context.PropertyValue as List<string>;
bool IsConvertable; foreach (var x in propertyValue) { ConvertHelper.ToT<TNumeric>(x, out IsConvertable); if (!IsConvertable) { returnfalse; } } returntrue; } }
擴充方法*```csharp ///
/// 是數字 Array,但允許空陣列或Null.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="TProperty">The type of the property.</typeparam>
/// <typeparam name="TNumeric">The type of the numeric.</typeparam>
/// <param name="ruleBuilder">The rule builder.</param>
/// <returns></returns>
public static IRuleBuilderOptions<T, TProperty> IsNumericArrayAllowEmpty<T, TProperty, TNumeric>(
this IRuleBuilder<T, TProperty> ruleBuilder)
where TNumeric : IComparable
{
return ruleBuilder.SetValidator(
new NumericArrayValidator<TNumeric>(allowEmpty: true));
}
/// <summary>
/// 是數字 Array.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="TProperty">The type of the property.</typeparam>
/// <typeparam name="TNumeric">The type of the numeric.</typeparam>
/// <param name="ruleBuilder">The rule builder.</param>
/// <returns></returns>
public static IRuleBuilderOptions<T, TProperty> IsNumericArray<T, TProperty, TNumeric>(
this IRuleBuilder<T, TProperty> ruleBuilder)
where TNumeric : IComparable
{
return ruleBuilder.SetValidator(
new NumericArrayValidator<TNumeric>(allowEmpty: false));
}
///<summary> /// Class QuadTreeService. ///</summary> publicstaticclassQuadTreeService { ///<summary> /// Inserts the specified node. ///</summary> ///<param name="node">The node.</param> ///<param name="data">The data.</param> ///<returns></returns> publicstaticboolInsert<T>(QuadTreeNode<T> node, T data) where T : IQuadTreeNodeData { // Bail if our coordinate is not in the boundingBox if (!CheckBoundingBoxContainData(node.BoundingBox, data)) { returnfalse; }
// Add the coordinate to the points array if ((node.Points.Count + 1) <= node.BucketCapacity) { node.Points.Add(data); returntrue; }
// Check to see if the current node is a leaf, if it is, split if (node.NorthWest == null) { Subdivide(node); }
// Traverse the tree if (Insert(node.NorthWest, data)) returntrue; if (Insert(node.NorthEast, data)) returntrue; if (Insert(node.SouthWest, data)) returntrue; if (Insert(node.SouthEast, data)) returntrue;
if (BoundingBox.LeftTop.Latitude.ToString() == BoundingBox.RightBottom.Latitude.ToString() && BoundingBox.LeftTop.Longitude.ToString() == BoundingBox.RightBottom.Longitude.ToString()) { //Point var Lng = range.LeftTop.Longitude <= BoundingBox.LeftTop.Longitude && BoundingBox.LeftTop.Longitude <= range.RightBottom.Longitude;
var Lat = range.RightBottom.Latitude <= BoundingBox.LeftTop.Latitude && BoundingBox.LeftTop.Latitude <= range.LeftTop.Latitude; return Lng && Lat; } else { var MinCx = Math.Max(range.LeftTop.Longitude, BoundingBox.LeftTop.Longitude); var MaxCy = Math.Min(range.LeftTop.Latitude, BoundingBox.LeftTop.Latitude);
var MaxCx = Math.Min(range.RightBottom.Longitude, BoundingBox.RightBottom.Longitude); var MinCy = Math.Max(range.RightBottom.Latitude, BoundingBox.RightBottom.Latitude);
voidMain() { Stopwatch timer = new Stopwatch(); timer.Reset(); timer.Start(); var YouWantToSearchData = new List<UserQuery.YourCoordinateData>(); for (int i = 0; i < 5000000; i++) { YouWantToSearchData.Add( new YourCoordinateData { Position = new Coordinate { Latitude = GetRandomNumber(22,26), Longitude = GetRandomNumber(120,122) } }); } var QuadTree = QuadTreeService.CreateQuadTree(YouWantToSearchData,GetBoundingBox()); //建立四元樹 string.Format("建資料花了: {0} ticks ({1} msec)", timer.ElapsedTicks, timer.ElapsedMilliseconds).Dump();
//要搜尋的範圍 BoundingBox range = new BoundingBox { LeftTop = new Coordinate { Latitude = 24.997123, Longitude = 121.21940612793 }, RightBottom = new Coordinate {Latitude =24.958553314209,Longitude = 121.485925} };
```csharp
/// Registers the type mappings with the Unity container.
/// The unity container to configure.
/// There is no need to register concrete types such as controllers or API controllers (unless you want to
/// change the defaults), as Unity allows resolving a concrete type even if it was not previously registered.
public static void RegisterTypes(IUnityContainer container)
{
publicclassPOIService { public List<POI> Get(string channelID) { var Result = new List<POI>(); var channel = GetChannel(channelID); //逐一搜尋頻道底下的各類別 foreach (var category in channel.Categorys) { //依據該類別所指定的供應商向Repository要資料 category.Supplier.ForEach(x => { switch (x) { case SupplierEnum.A: var ASupplier = new ASupplierRepository(); var APOIs = ASupplier.Get(); Result.AddRange(APOIs); break; case SupplierEnum.B: break; } }); } //並接總合的結果回傳 return Result; } ///<summary> /// 模擬頻道類別對應表 ///</summary> ///<param name="channelID">The channel identifier.</param> ///<returns>Channel.</returns> Channel GetChannel(string channelID) { if (channelID == "1") { returnnew Channel { ID = "1", Categorys = new List<Channel.Category> { new Channel.Category { Name = "交通", Supplier =new List<SupplierEnum> { SupplierEnum.A } } } }; } returnnew Channel { ID = channelID, Categorys = new List<Channel.Category> { new Channel.Category { Name = "交通", Supplier = new List<SupplierEnum> { SupplierEnum.A , SupplierEnum.B } } } }; } }
Application層
將傳入的ID透過Service去取得POI資料,並解用Json回傳 ****
```csharp
public ActionResult Index(string id)
{
var Service = new POIService();
var POIs = Service.Get(id);
return Json(POIs,JsonRequestBehavior.AllowGet);
}
//逐一搜尋頻道底下的各類別 foreach (var category in channel.Categorys) { //依據該類別所指定的供應商向Repository要資料 category.Supplier.ForEach(x => { switch (x) { case SupplierEnum.A: var ASupplier = new ASupplierRepository(); var APOIs = ASupplier.Get(); Result.AddRange(APOIs); break; case SupplierEnum.B: //補上B廠商 var BSupplier = new BSupplierRepository(); var BPOIs = BSupplier.Get(); Result.AddRange(BPOIs); break; } }); }
```csharp
public class SupplierFactory
{
public static ISupplierRepository Generate(SupplierEnum supplierType)
{
//因為A跟B的SupplierRepository都有實做ISupplierRepository
//所以這邊可以直接回傳介面,也間接地規範以後新增SupplierRepository都要實作ISupplierRepository介面
switch (supplierType)
{
case SupplierEnum.A:
return new ASupplierRepository();
case SupplierEnum.B:
return new BSupplierRepository();
}
return null;
}
}