Files
Christoph Schwörer f045b99a25 Codebasis als Dateien ins Arbeitsrepo statt als Gitlink
QuellCode/CentronERP war nur als Gitlink (Submodul-Referenz auf 79c1142)
getrackt, ohne .gitmodules und ohne erreichbares Remote. Der
Untersuchungsgegenstand der Versuchsreihe war damit nicht reproduzierbar
gesichert: Ein Klon haette ein leeres Verzeichnis erhalten, und die Belege
der 3.287 Anforderungen waeren nicht ueberpruefbar gewesen.

Umstellung:
- Historie nach c:\DEV\CentronERP_git_snapshot_79c1142 ausgelagert
  (vollstaendig lesbar, enthaelt 79c1142 und Vorgaenger 89ccfd6)
- Gitlink aus dem Index entfernt
- Dateiinhalt aufgenommen: 24.557 Dateien, rund 333 MB

Die verschachtelte .gitignore der Codebasis gilt weiter, Build-Artefakte
bleiben ausgeschlossen. Details in Versuche/Versuch_01/_Codebasis-Nachweis.md
2026-08-26 07:43:51 +02:00

273 lines
10 KiB
C#

using DevExpress.CodeParser;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text.RegularExpressions;
using Centron.Core;
namespace Centron.Tests.EndToEnd.Infrastructure.Verifier
{
public class CentronVerifierSettings
{
private readonly List<string> _ignoredColumns;
private readonly Dictionary<Type, List<string>> _ignoredProperties;
private readonly Dictionary<(Type type, string propertyName), List<(string regex, string replace)>> _cleanupProperties;
private readonly Dictionary<Type, List<string>> _noDateCleanupProperties;
public CentronVerifierSettings()
{
this._ignoredColumns = new List<string>();
this._ignoredProperties = new Dictionary<Type, List<string>>();
this._cleanupProperties = new Dictionary<(Type type, string propertyName), List<(string regex, string replace)>>();
this._noDateCleanupProperties = new Dictionary<Type, List<string>>();
this.CleanupGuidValues = true;
this.CleanupDateTimeValues = true;
this.CleanupDateTimeOffsetValues = true;
}
public void IgnoreColumn(string columnName)
{
this._ignoredColumns.Add(columnName);
}
public void IgnoreProperties<T>(params Expression<Func<T, object>> [] properties)
{
foreach (var property in properties)
this.IgnoreProperty(property);
}
public void IgnoreProperty<T>(Expression<Func<T, object>> property)
{
Guard.NotNull(property, nameof(property));
if (this._ignoredProperties.ContainsKey(typeof(T)) == false)
{
this._ignoredProperties[typeof(T)] = new List<string>();
}
this._ignoredProperties[typeof(T)].Add(this.GetPropertyName(property));
}
public void CleanupProperty<T>(Expression<Func<T, object>> property, string regex, string replace)
{
Guard.NotNull(property, nameof(property));
Guard.NotNullOrWhiteSpace(regex, nameof(regex));
//replace can be null
var propertyName = this.GetPropertyName(property);
var key = (typeof(T), propertyName);
if (this._cleanupProperties.ContainsKey(key) == false)
{
this._cleanupProperties[key] = new List<(string regex, string replace)>();
}
this._cleanupProperties[key].Add((regex, replace));
}
public void NoDateCleanup<T>(Expression<Func<T, string>> property)
{
Guard.NotNull(property, nameof(property));
var propertyName = this.GetPropertyName(property);
if (this._noDateCleanupProperties.ContainsKey(typeof(T)) == false)
{
this._noDateCleanupProperties[typeof(T)] = new List<string>();
}
this._noDateCleanupProperties[typeof(T)].Add(propertyName);
}
public void MergeWith(CentronVerifierSettings settings)
{
Guard.NotNull(settings, nameof(settings));
foreach (var ignoredProperty in settings._ignoredProperties)
{
if (this._ignoredProperties.ContainsKey(ignoredProperty.Key) == false)
{
this._ignoredProperties.Add(ignoredProperty.Key, new List<string>(ignoredProperty.Value)); //Make sure to create a copy of the list, so we can't change the original one by accident
}
else
{
this._ignoredProperties[ignoredProperty.Key].AddRange(ignoredProperty.Value);
}
}
foreach (var cleanupProperty in settings._cleanupProperties)
{
if (this._cleanupProperties.ContainsKey(cleanupProperty.Key) == false)
{
this._cleanupProperties.Add(cleanupProperty.Key, new List<(string, string)>(cleanupProperty.Value)); //Make sure to create a copy of the list, so we can't change the original one by accident
}
else
{
this._cleanupProperties[cleanupProperty.Key].AddRange(cleanupProperty.Value);
}
}
foreach (var noDate in settings._noDateCleanupProperties)
{
if (this._noDateCleanupProperties.ContainsKey(noDate.Key) == false)
{
this._noDateCleanupProperties.Add(noDate.Key, new List<string>(noDate.Value)); //Make sure to create a copy of the list, so we can't change the original one by accident
}
else
{
this._noDateCleanupProperties[noDate.Key].AddRange(noDate.Value);
}
}
this.CleanupGuidValues = settings.CleanupGuidValues || this.CleanupGuidValues;
this.CleanupDateTimeValues = settings.CleanupDateTimeValues || this.CleanupDateTimeValues;
this.CleanupDateTimeOffsetValues = settings.CleanupDateTimeOffsetValues || this.CleanupDateTimeOffsetValues;
}
public IContractResolver GetContractResolver()
{
return new VerifierContractResolver(this);
}
public List<string> GetIgnoredColumns()
{
return this._ignoredColumns;
}
public bool CleanupGuidValues { get; set; }
public bool CleanupDateTimeValues { get; set; }
public bool CleanupDateTimeOffsetValues { get; set; }
private string GetPropertyName<T, TResult>(Expression<Func<T, TResult>> property)
{
var unary = property.Body as UnaryExpression;
var expr = property.Body as MemberExpression ?? unary?.Operand as MemberExpression;
var prop = expr.Member as PropertyInfo;
return prop.Name;
}
#region Internal
private class VerifierContractResolver : DefaultContractResolver
{
private readonly CentronVerifierSettings _settings;
public VerifierContractResolver(CentronVerifierSettings settings)
{
Guard.NotNull(settings, nameof(settings));
this._settings = settings;
}
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
{
return base.CreateProperties(type, memberSerialization).OrderBy(f => f.PropertyName).ToList();
}
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
var property = base.CreateProperty(member, memberSerialization);
foreach (var ignoredProperty in this._settings._ignoredProperties)
{
if (property.DeclaringType.IsAssignableFrom(ignoredProperty.Key) && ignoredProperty.Value.Contains(property.PropertyName))
{
property.Ignored = true;
}
}
foreach (var cleanupProperty in this._settings._cleanupProperties)
{
if (property.DeclaringType.IsAssignableFrom(cleanupProperty.Key.type) && cleanupProperty.Key.propertyName == property.PropertyName)
{
foreach (var cleanup in cleanupProperty.Value)
{
property.ValueProvider = new CleanupValueProvider(property.ValueProvider, cleanup.regex, cleanup.replace);
}
}
}
if (property.PropertyType == typeof(string))
{
bool doNotCleanupDate = this._settings._noDateCleanupProperties
.Where(f => property.DeclaringType.IsAssignableFrom(f.Key))
.Where(f => f.Value.Contains(property.PropertyName))
.Any();
if (doNotCleanupDate == false)
property.ValueProvider = new CleanupDateValueProvider(property.ValueProvider);
}
return property;
}
}
private class CleanupValueProvider : IValueProvider
{
private readonly IValueProvider _inner;
private readonly string _regex;
private readonly string _replace;
public CleanupValueProvider(IValueProvider inner, string regex, string replace)
{
Guard.NotNull(inner, nameof(inner));
Guard.NotNullOrWhiteSpace(regex, nameof(regex));
//replace can be NULL
this._inner = inner;
this._regex = regex;
this._replace = replace;
}
public object GetValue(object target)
{
var value = this._inner.GetValue(target);
if (value == null)
return null;
return Regex.Replace((string)value, this._regex, this._replace);
}
public void SetValue(object target, object value)
{
this._inner.SetValue(target, value);
}
}
private class CleanupDateValueProvider : IValueProvider
{
private readonly IValueProvider _inner;
public CleanupDateValueProvider(IValueProvider inner)
{
Guard.NotNull(inner, nameof(inner));
this._inner = inner;
}
public object GetValue(object target)
{
var value = this._inner.GetValue(target);
if (value == null)
return null;
value = Regex.Replace((string)value, RegexHelper.Date, "EinDatum");
value = Regex.Replace((string)value, RegexHelper.RtfCreatedDate, string.Empty);
return value;
}
public void SetValue(object target, object value)
{
this._inner.SetValue(target, value);
}
}
#endregion
}
}