4

我正在工作一个 ASP.net MVC4 网站并且有模型和视图模型层。由于某些原因,我对 Model 和 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;
    }
}

但这有编译时错误:

4

1 回答 1

3

不幸的是,您无法通过反映属性本身的类型来获得用于装饰属性的属性。因此,我稍微修改了您的ViewModelPropertyName(this object) Extension 方法以获取所需属性的名称。

此方法现在将采用您希望获取其属性的属性的名称。如果属性存在,它将返回传递给其构造函数的值,另一方面,如果它不存在,它将简单地返回您传入的属性的名称。

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(this object, string) Extension 方法现在将在 TestClass 的实例上调用,而不是在属性本身上调用它。

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

        Console.Read();
    }
}
于 2013-08-07T22:43:17.233 回答