Auf der Grundlage von Firos Antwort habe ich das Problem gelöst. Allerdings gefiel mir die zu verwendende Syntax nicht ganz und die Tatsache, dass ich für die Standardwerte für jede Entität eine neue Klasse erstellen musste.
Die Syntax, die ich jetzt habe, sieht wie folgt aus:
mapping.ConstantValue(0).Column(@"client_id");
// or
mapping.ConstantValue(0, @"client_id");
Ich habe die folgenden Erweiterungsmethoden dafür erstellt:
public static PropertyPart
ConstantValue<TType, TValue>(this ClasslikeMapBase<TType> map, TValue value)
{
var getter =
new ConstantValueGetter<TValue>(CreateUniqueMemberName(), value);
ConstantValueAccessor.RegisterGetter(typeof(TType), getter);
var propertyInfo =
new GetterSetterPropertyInfo(typeof(TType), typeof(TValue),
getter.PropertyName, getter.Method, null);
var parameter = Expression.Parameter(typeof(TType), "x");
Expression body = Expression.Property(parameter, propertyInfo);
body = Expression.Convert(body, , typeof(object));
var lambda = Expression.Lambda<Func<TType, object>>(body, parameter);
return map.Map(lambda).Access.Using<ConstantValueAccessor>();
}
public static PropertyPart
ConstantValue<TType, TValue>(this ClasslikeMapBase<TType> map,
TValue value, string column)
{
return map.ConstantValue(value).Column(column);
}
Die wichtigsten Unterschiede sind:
-
Die erste dieser Erweiterungsmethoden gibt eine PropertyPart
und muss in Verbindung mit der Option Column
Methode, um anzugeben, welcher Spalte der konstante Wert zugeordnet werden soll. Aus diesem Grund ist der Spaltenname zum Zeitpunkt der Ausführung der Erweiterungsmethode nicht bekannt und wir müssen ihn selbst erstellen. Dies geschieht durch CreateUniqueMemberName
:
private static string CreateUniqueMemberName()
{
return "Dummy" + Guid.NewGuid().ToString("N");
}
-
Da man nur einen Typ als Zugriffsstrategie angeben kann und nicht eine Instanz, konnte ich nicht eine IPropertyAccessor
Implementierung konnte ich einfach eine IGetter
Instanz im Konstruktor. Das ist es, was ConstantValueAccessor.RegisterGetter(typeof(TType), getter);
löst. ConstantValueAccessor
hat eine statische Sammlung von Gettern:
internal class ConstantValueAccessor : IPropertyAccessor
{
private static readonly
ConcurrentDictionary<Type, SynchronizedCollection<IGetter>> _getters =
new ConcurrentDictionary<Type, SynchronizedCollection<IGetter>>();
public static void RegisterGetter(Type type, IGetter getter)
{
var getters =
_getters.GetOrAdd(type,
t => new SynchronizedCollection<IGetter>());
getters.Add(getter);
}
public IGetter GetGetter(Type theClass, string propertyName)
{
SynchronizedCollection<IGetter> getters;
if (!_getters.TryGetValue(theClass, out getters))
return null;
return getters.SingleOrDefault(x => x.PropertyName == propertyName);
}
// ...
}
Die Umsetzung der ConstantValueGetter<T>
ist die gleiche wie die unter dem angegebenen Link.
Weil es nicht so viel Spaß gemacht hat, sie zu implementieren. GetterSetterPropertyInfo
, aquí es ist. Ein wichtiger Unterschied ist, dass diese Implementierung keine Abhängigkeiten von (Fluent) NHibernate hat.