На основании ответа Firos я решил проблему. Однако мне не очень понравился используемый синтаксис и тот факт, что мне пришлось бы создавать новый класс для значений по умолчанию для каждой сущности.
Синтаксис, который я получил сейчас, выглядит следующим образом:
mapping.ConstantValue(0).Column(@"client_id");
// or
mapping.ConstantValue(0, @"client_id");
Я создал следующие методы расширения для него:
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);
}
Важные отличия:
Первый из этих методов расширения возвращает PropertyPart
и должен использоваться вместе с методом Column
, чтобы указать, какому столбцу должно быть сопоставлено постоянное значение. Из-за этого имя столбца неизвестно, когда выполняется метод расширения, и нам нужно создать его самостоятельно. Это сделано CreateUniqueMemberName
:
private static string CreateUniqueMemberName()
{
return "Dummy" + Guid.NewGuid().ToString("N");
}
Поскольку вы можете указать только тип в качестве стратегии доступа, но не экземпляр, я не смог создать реализацию IPropertyAccessor
, которая позволила мне просто передать экземпляр IGetter
в конструкторе. Вот что решает ConstantValueAccessor.RegisterGetter(typeof(TType), getter);
. ConstantValueAccessor
имеет статическую коллекцию геттеров:
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);
}
// ...
}
Реализация ConstantValueGetter<T>
такая же, как в приведенной ссылке.
Потому что реализовать GetterSetterPropertyInfo
, здесь было не очень весело это так. Одним из важных отличий является то, что эта реализация не имеет никаких зависимостей от (Свободно) NHibernate.