Based on Firos answer, I solved the problem. However, I didn’t quite like the syntax used and the fact that I would need to create a new class for the default values for each object.
The syntax I received now looks like this:
mapping.ConstantValue(0).Column(@"client_id"); // or mapping.ConstantValue(0, @"client_id");
I created the following extension methods for it:
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); }
Important differences are:
The first of these extension methods returns a PropertyPart and should be used in conjunction with the Column method to indicate in which column the constant value should be mapped. Because of this, the column name is not known when the extension method is executed, and we must create it ourselves. This is done using CreateUniqueMemberName :
private static string CreateUniqueMemberName() { return "Dummy" + Guid.NewGuid().ToString("N"); }
Since you can only specify a type as an access strategy, not an instance, I could not create an IPropertyAccessor implementation IPropertyAccessor that I could just pass the IGetter instance in the constructor. What ConstantValueAccessor.RegisterGetter(typeof(TType), getter); solves ConstantValueAccessor.RegisterGetter(typeof(TType), getter); . ConstantValueAccessor has a static set of getters:
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); }
The implementation of ConstantValueGetter<T> is the same as the referenced link.
Because it wasn’t so much fun to implement GetterSetterPropertyInfo , here . An important difference is that this implementation has no dependencies on (Fluent) NHibernate.
source share