实体框架6重用数据注释 [英] Entity Framework 6 Reusing Data Annotations

查看:207
本文介绍了实体框架6重用数据注释的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经看了一会儿一个明确的解决方案,以这一点,但还没有得出结论。我想在数据模型类只有一次指定数据批注,并通过这些从视图模型类的用户界面,而无需再次指定它们可以看出。为了说明我的观点假设我有一个UserAccount类这样...

I've looked for a while for a definitive solution to this but have yet to come to a conclusion. I would like to specify data annotations just once on the data model class and have these be seen by the UI from a view model class without specifying them again. To illustrate my point suppose I have a UserAccount Class as such...

public class UserAccount
{
    [Display(Name = "Username", Prompt = "Login As"), Required()]
    string UserName { get; set; }
    [Display(Name = "Password", Prompt = "Password"), Required(), DataType(DataType.Password), StringLength(255, MinimumLength = 7, ErrorMessage = "The password must be at least 7 characters")]
    string Password { get; set; }
}

现在我想指定其中包含一个密码确认字段视图模型这将不会被存储在数据库中以及潜在的其他的数据模型,但我不希望有指定所有数据注解再次属性。这是试图找到最佳实践,同时也多次声明需要保持并在某些时候人会被修改而另一些则不会。

now I would like to specify a View Model which contains a password confirmation field that wouldn't be stored in the database and potentially other data models but I don't want to have to specify all the data annotation attributes again. This is about trying to find best practice, but also multiple declarations need maintaining and at some point one will get modified and the others won't.

我已经看了一个接口/继承解决方案,但并没有真正完全削减对各种原因。另外一个潜在的解决方案可能是对视图模型类的属性(或属性)说继承...属性,但我找不到适合这个尚未事情。

I've looked at an Interfaces/Inheritance solution but that doesn't really cut it fully for various reasons. One other potential solution might be to have an Attribute on the View Model class (or properties) to say inherit attributes from... but I can't find anything suitable as yet for this.

有没有人有什么好主意或以合适的方式来实现这一点?

Has anyone got any bright ideas or implemented this in a suitable fashion?

推荐答案

下面是一个解决方案,我已经想出考虑其他可能的解决方案后,提出的问题。它是基于发现下面的文章...

Here's a solution I've come up with after considering the other possible solutions posed. It's based on finding the following article...

http://jendaperl.blogspot.co.uk/2010/10/attributeproviderattribute-rendered.html

我的理由这个比别人在这个岗位的底部表述的。

My reasons for this over others are stated at the bottom of this post.

有一个现有的数据模型类的...

Having an existing Data Model class of...

public class UserAccount
{
     [Display(Name = "Username", Prompt = "Login As"), Required()]
     string UserName { get; set; }
     [Display(Name = "Password", Prompt = "Password"), Required(), DataType(DataType.Password), StringLength(255, MinimumLength = 7, ErrorMessage = "The password must be at least 7 characters")]
     string Password { get; set; }
}



那岂不是巨大的,如果我们可以只复制属性的属性变成使用它的一个观点,也许他们重写,如果我们需要这样使用这个类的观点并不需要一个简单的属性更改将再谈。这里是我的解决方案。创建一个新的属性如下...

wouldn't it be great if we could just copy the property attributes into a view that use it, maybe override them if we need to so that the views that use this class don't need to be revisted on a simple attribute change. Here's my solutions. Create a new attribute as below...

using System.ComponentModel;

namespace MyApp.ViewModels
{
    public class AttributesFromAttribute : AttributeProviderAttribute
    {
        public AttributesFromAttribute(Type type, string property)
            : base(type.AssemblyQualifiedName, property)
        {
        }

        public T GetInheritedAttributeOfType<T>() where T : System.Attribute
        {
            Dictionary<string,object> attrs = Type.GetType(this.TypeName).GetProperty(this.PropertyName).GetCustomAttributes(true).ToDictionary(a => a.GetType().Name, a => a);
            return attrs.Values.OfType<T>().FirstOrDefault();
        }

    }
}

现在你只需添加下列有关物业在视图模型类...

now you can just add the following to the relevant property in the view model class...

[AttributesFrom(typeof(MyApp.DataModel.UserAccount), "UserName")]

例如..

public class RegisterViewModel
{
    public UserAccount UserAccount { get; set; }
    public RegisterViewModel()
    {
        UserAccount = new UserAccount();
    }

    [AttributesFrom(typeof(MyApp.DataModel.UserAccount), "UserName")]
    string UserName { get; set; }
    [AttributesFrom(typeof(MyApp.DataModel.UserAccount), "Password")]
    string Password { get; set; }

    [AttributesFrom(typeof(MyApp.DataModel.UserAccount), "Password")]
    [Display(Name = "Confirm Password", Prompt = "Confirm Password"), Compare("Password", ErrorMessage = "Your confirmation doesn't match.")]
    public string PasswordConfirmation { get; set; }

}

这则提供了可以覆盖属性的复制(与上述PasswordConfirmation),允许在同一个视图模型多个数据模型,如果你需要访问从代码中继承的属性,你可以这样做使用GetInheritedAttributeOfType方法。例如...

This then gives copying of attributes that can be overridden (as with PasswordConfirmation above) allowing for multiple data models in the same viewmodel and if you need to access the inherited attributes from code, you can do so using the GetInheritedAttributeOfType method. For example...

public static class AttrHelper
{
   public static T GetAttributeOfType<T>(this ViewDataDictionary viewData) where T : System.Attribute
    {
        var metadata = viewData.ModelMetadata;
        var prop = metadata.ContainerType.GetProperty(metadata.PropertyName);
        var attrs = prop.GetCustomAttributes(false);

        // Try and get the attribute directly from the property.
        T ret = attrs.OfType<T>().FirstOrDefault();

        // If there isn't one, look at inherited attribute info if there is any.
        if(ret == default(T))
        {
            AttributesFromAttribute inheritedAttributes = attrs.OfType<AttributesFromAttribute>().FirstOrDefault();
            if (inheritedAttributes != null)
            {
                ret = inheritedAttributes.GetInheritedAttributeOfType<T>();
            }
        }

        // return what we've found.
        return ret;
    }
}

这可以从编辑模板,例如调用。 ..

This can be called from an Editor Template for example...

var dataTypeAttr = AttrHelper.GetAttributeOfType<DataTypeAttribute>(ViewData);

这将首先来看一下视图模型的财产属性直接,但如果什么也没有发现,将着眼于继承的属性与它的调用GetInheritedAttributeOfType。

which will first look at the viewmodel's property attributes directly but if nothing's found it will look at the inherited attributes with it's call to GetInheritedAttributeOfType.

这最适合我,因为...

This works best for me because...


  1. 我觉得在的ViewModels还有datamodels重复DataAnnotations的目前的做法是不是伟大的可维护性和重用。

  1. I feel that current practice of repeating DataAnnotations in viewmodels as well as the datamodels isn't great for maintainability or reuse.

使用MetadataType是也缺乏灵活性,这是全有或全无,你不能包含在一个单一的视图模型多MetadataType属性。

Using MetadataType is also inflexible, it's all or nothing and you can't include multiple MetadataType attributes on a single ViewModel.

封装datamodels中的ViewModels无属性缺乏作为它也没有的flexability。你必须包括整个封装的对象,以便在多个视图可以不填充数据模型。

Encapsulating the datamodels in the viewmodels without Properties is lacking as it also doesn't have the flexability. You have to include the entire encapsulated object so cannot populate the DataModel over multiple views.

这篇关于实体框架6重用数据注释的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆