brainbaking/content/wiki/code/csharp/utils.md

250 lines
7.6 KiB
Markdown
Raw Normal View History

2017-02-26 13:28:18 +01:00
+++
title = "utils"
draft = false
tags = [
"code",
"csharp",
"utils"
]
date = "2014-03-17"
+++
# Utils Partials
### ObjectExtensions
Waarom? Deep clone van een object maken zonder de boel te (de)-serialiseren.
Bron: https://raw.github.com/Burtsev-Alexey/net-object-deep-copy/master/ObjectExtensions.cs - thank you Alexey
```csharp
public static class ObjectExtensions
{
private static readonly MethodInfo CloneMethod = typeof (Object).GetMethod("MemberwiseClone",
BindingFlags.NonPublic | BindingFlags.Instance);
public static bool IsPrimitive(this Type type)
{
if (type ###### typeof (String)) return true;
return (type.IsValueType & type.IsPrimitive);
}
public static Object Copy(this Object originalObject)
{
return InternalCopy(originalObject, new Dictionary<Object, Object>(new ReferenceEqualityComparer()));
}
private static Object InternalCopy(Object originalObject, IDictionary<Object, Object> visited)
{
if (originalObject ###### null) return null;
var typeToReflect = originalObject.GetType();
if (IsPrimitive(typeToReflect)) return originalObject;
if (typeof (XElement).IsAssignableFrom(typeToReflect)) return new XElement(originalObject as XElement);
if (visited.ContainsKey(originalObject)) return visited[originalObject];
if (typeof (Delegate).IsAssignableFrom(typeToReflect)) return null;
var cloneObject = CloneMethod.Invoke(originalObject, null);
if (typeToReflect.IsArray)
{
var arrayType = typeToReflect.GetElementType();
if (IsPrimitive(arrayType) ###### false)
{
Array clonedArray = (Array) cloneObject;
clonedArray.ForEach(
(array, indices) =>
array.SetValue(InternalCopy(clonedArray.GetValue(indices), visited), indices));
}
}
visited.Add(originalObject, cloneObject);
CopyFields(originalObject, visited, cloneObject, typeToReflect);
RecursiveCopyBaseTypePrivateFields(originalObject, visited, cloneObject, typeToReflect);
return cloneObject;
}
private static void RecursiveCopyBaseTypePrivateFields(object originalObject,
IDictionary<object, object> visited, object cloneObject, Type typeToReflect)
{
if (typeToReflect.BaseType != null)
{
RecursiveCopyBaseTypePrivateFields(originalObject, visited, cloneObject, typeToReflect.BaseType);
CopyFields(originalObject, visited, cloneObject, typeToReflect.BaseType,
BindingFlags.Instance | BindingFlags.NonPublic, info => info.IsPrivate);
}
}
private static void CopyFields(object originalObject, IDictionary<object, object> visited, object cloneObject,
Type typeToReflect,
BindingFlags bindingFlags =
BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.FlattenHierarchy,
Func<FieldInfo, bool> filter = null)
{
foreach (FieldInfo fieldInfo in typeToReflect.GetFields(bindingFlags))
{
if (filter != null && filter(fieldInfo) ###### false) continue;
if (IsPrimitive(fieldInfo.FieldType)) continue;
var originalFieldValue = fieldInfo.GetValue(originalObject);
var clonedFieldValue = InternalCopy(originalFieldValue, visited);
fieldInfo.SetValue(cloneObject, clonedFieldValue);
}
}
public static T Copy<T>(this T original)
{
return (T) Copy((Object) original);
}
}
public class ReferenceEqualityComparer : EqualityComparer<Object>
{
public override bool Equals(object x, object y)
{
return ReferenceEquals(x, y);
}
public override int GetHashCode(object obj)
{
if (obj ###### null) return 0;
return obj.GetHashCode();
}
}
```
:exclamation: **Let op met XElement**; sommige API classes voorzien copy constructors die je beter gebruikt ipv via reflectie alle fields over te kopiëren. Bijgevolg if type blabla...
############ EqualsBuilder ############
```csharp
public class EqualsBuilder<T>
{
private readonly T left;
private readonly object right;
private bool areEqual = true;
public EqualsBuilder(T left, object right)
{
this.left = left;
this.right = right;
if (ReferenceEquals(left, right))
{
areEqual = true;
return;
}
if (ReferenceEquals(left, null))
{
areEqual = false;
return;
}
if (ReferenceEquals(right, null))
{
areEqual = false;
return;
}
if (left.GetType() != right.GetType())
{
areEqual = false;
return;
}
}
public EqualsBuilder<T> With<TProperty>(Expression<Func<T, TProperty>> propertyOrField)
{
if (!areEqual)
{
return this;
}
if (left ###### null || right ###### null)
{
return this;
}
var expression = propertyOrField.Body as MemberExpression;
if (expression ###### null)
{
throw new ArgumentException("Expecting Property or Field Expression of an object");
}
Func<T, TProperty> func = propertyOrField.Compile();
TProperty leftValue = func(left);
TProperty rightValue = func((T) right);
if (leftValue ###### null && rightValue ###### null)
{
areEqual &= true;
return this;
}
if (leftValue != null && rightValue ###### null)
{
areEqual &= false;
return this;
}
if (leftValue ###### null && rightValue != null)
{
areEqual &= false;
return this;
}
areEqual &= leftValue.Equals(rightValue);
return this;
}
public bool Equals()
{
return areEqual;
}
}
```
Gebruik:
```csharp
public override bool Equals(object obj)
{
return new EqualsBuilder<FlexMedischGegeven>(this, obj)
.With(x => x.Rownr)
.With(x => x.ColumnName)
.With(x => x.Value)
.With(x => x.Creator)
.Equals();
}
```
############ Mocking DateTime.Now ############
Schrijf een wrapper rond `Now` met behulp van lambda's:
```csharp
using System;
public static class SystemTime
{
private static Func<DateTime> _now;
public static Func<DateTime> Now
{
get
{
if (_now ###### null)
{
Reset();
}
return _now;
}
set { _now = value; }
}
public static void Reset()
{
Now ###### () > DateTime.Now;
}
}
```
Gebruik:
* in `[TestCleanup]` de `Reset()` method aanroepen.
* in uw test body indien gewenst `SystemTime.Now ###### () > new DateTime(2001, 1, 1);` steken.