Я создаю приложение ASP.NET MVC 2 на C # и успешно использую Automapper для сопоставления значений между ViewModels и бизнес-объектами.
В дополнение к нескольким явным свойствам, мои бизнес-объекты оборачивают словарь как ловушку для всех свойств, которые не определены явно. Нечто похожее на:
public class MyBusinessObject {
public void SetExtraPropertyValue<T>(string key, T value) {
// ...
}
public T GetExtraPropertyValue<T>(string key, T defaultValue) {
// ...
}
}
В моей ViewModel у меня есть свобода создавать любые свойства, которые я хочу, но я не могу изменять бизнес-объекты.
Допустим, я создал модель вида, подобную этой:
class MyViewModel {
public string CustomProp { get; set; }
}
и значение, которое я хочу сохранить и получить, нужно будет использовать
businessModelInstance.SetExtraPropertyValue("CustomProp", newVal);
и
businessModelInstance.GetExtraPropertyValue("CustomProp");
У меня проблемы в обоих направлениях.
Во-первых, при переходе от MyBusinessObject к MyViewModel я подумал, что это должно быть просто сделать в моем пользовательском профиле Automapper:
CreateMap<MyBusinessObject, MyViewModel>()
.ForMember(dest => dest.CustomProp,
opt => opt.MapFrom(s => s.GetExtraPropertyValue("CustomProp", "")));
Однако MyBusinessObject.CustomProp
никогда не заполняется, хотя есть и другие свойства.
Во-вторых, я не знаю, как настроить получение значения от MyViewModel.CustomProp
до вызова MyBusinessObject.SetExtraPropertyValue
.
- Есть ли способ сделать это
сопоставление с Automapper?
- Есть ли совсем другая атака, которую я
должен пытаться?
- Нужно ли прибегать к ручному отображению в моем контроллере? Например,
MyBusinessObject.SetExtraPropertyValue("CustomProp",
MyViewModel.CustomProp)
1036 **
ОБНОВЛЕНИЕ : Вот мое решение, основанное на предложениях @Patrick Steele:
Я добавил пользовательский атрибут к свойствам модели представления, который я хотел отобразить на дополнительные ключи свойств. Пользовательский TypeConverter использует отражение, чтобы найти эти атрибуты и свойства карты соответственно.
public class ItemExtraPropertyConverter : ITypeConverter<MyViewModel, MyBusinessObject>
{
public MyBusinessObject Convert(ResolutionContext context)
{
var destination = context.DestinationValue as MyBusinessObject;
if (destination == null )
throw new InvalidOperationException("Destination type is not of type MyBusinessObject");
foreach (var property in context.SourceType.GetProperties())
foreach (var attribute in property.GetCustomAttributes(true).OfType<ExtraPropertyAttribute>())
{
var key = attribute.Key;
if (string.IsNullOrEmpty(key))
key = property.Name;
destination.SetExtraPropertyValue(key, property.GetValue(context.SourceValue, null));
}
return destination;
}
}
public class ExtraPropertyAttribute : Attribute
{
public ExtraPropertyAttribute()
{
}
public ExtraPropertyAttribute(string key)
{
Key = key;
}
public string Key { get; set; }
}
public class MyViewModel
{
[ExtraProperty]
public string CustomProp { get; set; }
[ExtraProperty("OtherPropertyValue")]
public string CustomProp2 { get; set; }
}
В методе настройки класса пользовательского профиля:
CreateMap<MyViewModel, MyBusinessObject>()
.ConvertUsing<ItemExtraPropertyConverter>();