2013-08-07 4 views
2

Я работаю на веб-сайте ASP.net MVC4 и имею модель & Просмотрите модельный слой. Из-за определенных причин у меня есть разные имена для нескольких объектов в модели и ViewModelМетод расширения для пользовательских атрибутов

Модель

public partial class Project 
{ 
    public string Desc {get; set;} 
} 

вид Модель

public class ProjectViewModel 
{ 
    public string Description { get; set; } 
} 

Теперь у модели слоя, мне нужно используйте ViewModel имя свойства, если оно отличается. Я думал о создании пользовательского атрибута, так что я могу иметь что-то вроде этого в моделях:

public partial class Project 
{ 
    [ViewModelPropertyName("Description")] 
    public string Desc {get;set;} 
} 

и использовать его на уровне модели, как

string.Format("ViewModel Property Name is {0}", this.Desc.ViewModelPropertyName()) 

Я хочу, чтобы это родовое, так что если есть нет атрибута ViewModelPropertyName для свойства, тогда он должен возвращать то же имя свойства, то есть если свойство Desc не имеет атрибута, оно должно возвращать только "Desc".

Вот что я пытался

public class ViewModelPropertyNameAttribute : System.Attribute 
{ 
    #region Fields 

    string viewModelPropertyName; 

    #endregion 

    #region Properties 

    public string GetViewModelPropertyName() 
    { 
     return viewModelPropertyName; 
    } 

    #endregion 

    #region Constructor 

    public ViewModelPropertyNameAttribute(string propertyName) 
    { 
     this.viewModelPropertyName = propertyName; 
    } 

    #endregion 
} 

Нужна помощь для того, как получить доступ к пользовательский атрибут

Текущее состояние

public static class ModelExtensionMethods 
{ 
    public static string ViewModelPropertyName(this Object obj) 
    { 
     // ERROR: Cannot convert from 'object' to 'System.Reflect.Assembly' 
     System.Attribute[] attrs = System.Attribute.GetCustomAttributes(obj); 

     foreach (System.Attribute attr in attrs) 
     { 
      if (attr is ViewModelPropertyNameAttribute) 
      { 
       return ((ViewModelPropertyNameAttribute)attr).GetViewModelPropertyName(); 
      } 
     } 

     return string.Empty; 
    } 
} 

Но есть ошибка компиляции времени:

+0

'this.Desc.ViewModelPropertyName' должно быть' this.Desc.GetViewModelPropertyName() '. Нет такой вещи, как свойство расширения. – Khan

+0

Typo, я имел в виду только это. Спасибо – Rohit

ответ

1

К сожалению, вы не можете получить атрибуты, которые вы использовали для украшения свойств, отражая тип самого свойства. Поэтому я изменил ваш ViewModelPropertyName (этот объект) Метод расширения немного, чтобы взять имя вашего желаемого свойства.

Этот метод теперь примет имя свойства, атрибут которого вы хотите получить. Если атрибут существует, то он будет возвращать значение, переданное в его конструктор, если он с другой стороны, не существует, она просто возвращает имя свойства, которое прошло в.

public static class ModelExtensionMethods 
{ 
    public static string ViewModelPropertyName(this object obj, string name) 
    { 
     var attributes = obj.GetType() 
          .GetCustomAttributes(true) 
          .OfType<MetadataTypeAttribute>() 
          .First() 
          .MetadataClassType 
          .GetProperty(name) 
          .GetCustomAttributes(true); 

     if (attributes.OfType<ViewModelPropertyNameAttribute>().Any()) 
     { 
      return attributes.OfType<ViewModelPropertyNameAttribute>() 
          .First() 
          .GetViewModelPropertyName(); 
     } 
     else 
     { 
      return name; 
     } 
    } 
} 

Вы также можете определить следующие классов для проверки этого нового подхода.

[MetadataType(typeof(TestClassMeta))] 
class TestClass { } 

class TestClassMeta 
{ 
    [ViewModelPropertyName("TheName")] 
    public string FirstName { get; set; } 

    public string LastName { get; set; } 
} 

Кроме того, как вы можете видеть из следующих строк кода, ваш ViewModelPropertyName (этот объект, строка) метод расширения теперь будет называться по экземпляру ваших TestClass, вместо того, чтобы называть его по недвижимости сам.

class Program 
{ 
    static void Main() 
    { 
     Console.WriteLine(new TestClass().ViewModelPropertyName("FirstName")); 
     Console.WriteLine(new TestClass().ViewModelPropertyName("LastName")); 

     Console.Read(); 
    } 
} 
+0

Спасибо Марио, но я сталкиваюсь с проблемой с его внедрением.Я использую классы meta или buddy для моделей, и GetCustomAttributes не смог найти атрибут ViewModelPropertyName – Rohit

+0

Я не уверен, какая настройка у вас там есть, но я отредактировал свой ответ на то, что, по вашему мнению, вы используете. Теперь метод расширения сначала возьмет атрибут из метакласса и выполнит поиск его свойств для других атрибутов, прежде чем вернуть требуемое значение. Я также создал мета-класс, который украшен новым атрибутом и содержит необходимые свойства, а не оригинальный TestClass. –

+0

Спасибо, что так много. Это действительно работало как прелесть. +100 – Rohit

Смежные вопросы