На основании ответа 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
и должен использоваться в сочетании с th e 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
, here это так. Важным отличием является то, что эта реализация не имеет никаких зависимостей от (Fluent) NHibernate.
Спасибо большое, это отлично выглядит. Я проверю его в выходные. –
Это работает ! :) Пожалуйста, посмотрите мой ответ на несколько иной подход - что вы думаете об этом? –