Использование Automappper для сопоставления с методами - PullRequest
0 голосов
/ 27 ноября 2010

Я создаю приложение 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>();

1 Ответ

0 голосов
/ 03 декабря 2010

Мне кажется, что что-то не так с вашими реализациями GetExtraPropertyValue и SetExtraPropertyValue. Я собрал быстрый тест, и приведенное выше сопоставление сработало, как и ожидалось. Вот реализация, которую я использовал для теста:

public class MyBusinessObject
{
    private readonly Dictionary<string, object> extraProperties = new Dictionary<string, object>();

    public int Id { get; set; }
    public string Name { get; set; }

    public void SetExtraPropertyValue<T>(string key, T value)
    {
        extraProperties.Add(key, value);
    }
    public T GetExtraPropertyValue<T>(string key, T defaultValue)
    {
        if (extraProperties.ContainsKey(key))
        {
            return (T)extraProperties[key];
        }

        return defaultValue;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...