使用 System.ComponentModel.DataAnnotations 时有什么方法可以禁用验证吗?

发布于 2024-10-13 09:02:36 字数 5366 浏览 4 评论 0原文

不幸的是,这里的其他查询并没有回答我的问题,我希望在这个问题上能有天才的一击。

目前的问题是我有一个域对象“GamePlayer”,它有许多 DataAnnotations 来对从 UI 传入的数据提供模型验证。这些工作很不错,并且是完全可测试的等等。

然而,我们有一个数据库,其中的数据在几年内允许随意增长(大约 660,000 个用户帐户),我想说目前有 20,000 到 50,000 个帐户违反了我们在 GamePlayer 对象上设置的规则。

因此,我希望能够做的仍然是使用数据注释,但能够在从数据库到模型总体的过程中“禁用”它们。

我知道,如果我使用 ModelMetaData 内容并将验证属性存储在另一个类中并将主类与 [MetadataType(typeof(GamePlayerMetadata))] 相关联,我可以这样做:

TypeDescriptor.AddProvider(new AssociatedMetadataTypeTypeDescriptionProvider(typeof(GamePlayer), typeof(GamePlayerMetadata)), typeof(GamePlayer));

因此,执行相反的操作 (.RemoveProvider) 以删除规则 - 这是可行的,尽管我不想使用 ModelMetaData 类并将其全部保留在一个中(如果可以的话)?

希望不要太胡言乱语:)

干杯任何帮助, Terry

希望支持这种情况的附加信息:

[Serializable]
[MetadataType(typeof(AddressMetadata))]
public class Address
{
    [NonSerialized]
    private readonly AssociatedMetadataTypeTypeDescriptionProvider metadataAddress;

    public string House { get; private set; }
    public string SubPremises { get; private set; }
    public string Street { get; private set; }
    public string Town { get; private set; }
    public string County { get; private set; }
    public string Country { get; private set; }
    public string Postcode { get; private set; }


    internal Address()
    {
        metadataAddress             = new AssociatedMetadataTypeTypeDescriptionProvider(typeof(Address), typeof(AddressMetadata));
        TypeDescriptor.AddProviderTransparent(metadataAddress, typeof(Address));
    }

    internal Address(AddressDto address) : this()
    {
        this.House          = address.House;
        this.SubPremises    = address.SubPremises;
        this.Street         = address.Street;
        this.Town           = address.Town;
        this.County         = address.County;
        this.Country        = address.Country;
        this.Postcode       = address.Postcode;
    }

    public Address(string house, string subPremises, string street, string town, string county, string country, string postcode) : this()
    {
        SetAddress(house, subPremises, street, town, county, country, postcode);
    }


    #region ------------------------------------------------------------------------------------- Methods --
    public bool IsSet()
    {
        return !((String.IsNullOrEmpty(House) && String.IsNullOrEmpty(this.SubPremises)) && String.IsNullOrEmpty(Postcode) && String.IsNullOrEmpty(Street));
    }

    /// <exception cref="ValidationException">Thrown when one of the fields doesn't match the business complexity rules</exception>
    public void SetAddress(string house, string subPremises, string street, string town, string county, string country, string postcode)
    {
        Validator.ValidateProperty(house, new ValidationContext(this, null, null) { MemberName = "House" });
        Validator.ValidateProperty(street, new ValidationContext(this, null, null) { MemberName = "Street" });
        Validator.ValidateProperty(postcode, new ValidationContext(this, null, null) { MemberName = "Postcode" });

        House = house;
        SubPremises = subPremises;
        Street = street;
        Town = town;
        County = county;
        Country = country;
        Postcode = postcode;
    }


    /// <exception cref="ValidationException">Thrown when one of the fields doesn't match the business complexity rules</exception>
    public void SetAddress(Address newAddress)
    {
        this.SetAddress(newAddress.House, newAddress.SubPremises, newAddress.Street, newAddress.Town, newAddress.County, newAddress.Country, newAddress.Postcode);
    }


    public string FirstLineOfAddress
    {
        get
        {
            return String.Format("{0}{1}, {2}",
                                    (String.IsNullOrEmpty(this.SubPremises) ? "" : this.SubPremises),
                                    (String.IsNullOrEmpty(this.SubPremises) ? this.House : ", " + this.House),
                                    this.Street
                );
        }
    }

    public override string ToString()
    {
        return String.Format("{0}, {1}, {2}, {3}, {4}, {5}, {6}",
                                House,
                                SubPremises,
                                Street,
                                Town,
                                County,
                                Postcode,
                                Country);
    }

    public AddressDto ToAddressDto()
    {
        return new AddressDto { House = this.House, SubPremises = this.SubPremises, Street = this.Street,
                                    Town = this.Town, County = this.County, Country = this.Country, Postcode = this.Postcode };
    }

    public void DisableValidation()
    {
        TypeDescriptor.RemoveProviderTransparent(metadataAddress, typeof(Address));
    }
    #endregion

}

为了简单起见,让我们假设“House”上的 AddressMetadata 有一个 [Required] 属性,尽管显然我也有邮政编码等的正则表达式。

假设我正在同一个程序集中工作,因此内部修饰符并不重要。

现在,如果我调用:

Address stuff = new Address("", "", "", "", "", "", "");

然后验证就会启动(通过 SetAddress) no根本就是问题。

如果我这样做:

Address stuff = new Address();
stuff.DisableValidation();
stuff.SetAddress("", "", "", "", "", "", "");

我希望验证被禁用。

这对任何人提供更多信息有帮助吗?

The other queries on here don't unfortunately answer my question, and I'm hoping for a stroke of genius on this one.

The problem currently is I have a domain object 'GamePlayer' which has a number of DataAnnotations to provide model validation on data incoming from the UI. These work a treat, and are fully testable etc.

We however have a database where the data has been allowed to grow haphazardly over a period of years (approximately 660,000 user accounts), and I'd say between 20,000 and 50,000 accounts currently violate the rules that we've put in place on the GamePlayer object.

So, what I hope to be able to do is still use Data Annotations, but be able to 'disable' them on the way from the DB up to the population of the model.

I know that if I use the ModelMetaData stuff and store the validation attributes in another class and associate the main class with [MetadataType(typeof(GamePlayerMetadata))], I can do:

TypeDescriptor.AddProvider(new AssociatedMetadataTypeTypeDescriptionProvider(typeof(GamePlayer), typeof(GamePlayerMetadata)), typeof(GamePlayer));

and hence, do the reverse (.RemoveProvider) to remove the rules - this works, though I'd rather not use the ModelMetaData class and keep it all in one if I can?

Hopefully not waffled too much :)

Cheers for any help,
Terry

Additional Information to hopefully support the case:

[Serializable]
[MetadataType(typeof(AddressMetadata))]
public class Address
{
    [NonSerialized]
    private readonly AssociatedMetadataTypeTypeDescriptionProvider metadataAddress;

    public string House { get; private set; }
    public string SubPremises { get; private set; }
    public string Street { get; private set; }
    public string Town { get; private set; }
    public string County { get; private set; }
    public string Country { get; private set; }
    public string Postcode { get; private set; }


    internal Address()
    {
        metadataAddress             = new AssociatedMetadataTypeTypeDescriptionProvider(typeof(Address), typeof(AddressMetadata));
        TypeDescriptor.AddProviderTransparent(metadataAddress, typeof(Address));
    }

    internal Address(AddressDto address) : this()
    {
        this.House          = address.House;
        this.SubPremises    = address.SubPremises;
        this.Street         = address.Street;
        this.Town           = address.Town;
        this.County         = address.County;
        this.Country        = address.Country;
        this.Postcode       = address.Postcode;
    }

    public Address(string house, string subPremises, string street, string town, string county, string country, string postcode) : this()
    {
        SetAddress(house, subPremises, street, town, county, country, postcode);
    }


    #region ------------------------------------------------------------------------------------- Methods --
    public bool IsSet()
    {
        return !((String.IsNullOrEmpty(House) && String.IsNullOrEmpty(this.SubPremises)) && String.IsNullOrEmpty(Postcode) && String.IsNullOrEmpty(Street));
    }

    /// <exception cref="ValidationException">Thrown when one of the fields doesn't match the business complexity rules</exception>
    public void SetAddress(string house, string subPremises, string street, string town, string county, string country, string postcode)
    {
        Validator.ValidateProperty(house, new ValidationContext(this, null, null) { MemberName = "House" });
        Validator.ValidateProperty(street, new ValidationContext(this, null, null) { MemberName = "Street" });
        Validator.ValidateProperty(postcode, new ValidationContext(this, null, null) { MemberName = "Postcode" });

        House = house;
        SubPremises = subPremises;
        Street = street;
        Town = town;
        County = county;
        Country = country;
        Postcode = postcode;
    }


    /// <exception cref="ValidationException">Thrown when one of the fields doesn't match the business complexity rules</exception>
    public void SetAddress(Address newAddress)
    {
        this.SetAddress(newAddress.House, newAddress.SubPremises, newAddress.Street, newAddress.Town, newAddress.County, newAddress.Country, newAddress.Postcode);
    }


    public string FirstLineOfAddress
    {
        get
        {
            return String.Format("{0}{1}, {2}",
                                    (String.IsNullOrEmpty(this.SubPremises) ? "" : this.SubPremises),
                                    (String.IsNullOrEmpty(this.SubPremises) ? this.House : ", " + this.House),
                                    this.Street
                );
        }
    }

    public override string ToString()
    {
        return String.Format("{0}, {1}, {2}, {3}, {4}, {5}, {6}",
                                House,
                                SubPremises,
                                Street,
                                Town,
                                County,
                                Postcode,
                                Country);
    }

    public AddressDto ToAddressDto()
    {
        return new AddressDto { House = this.House, SubPremises = this.SubPremises, Street = this.Street,
                                    Town = this.Town, County = this.County, Country = this.Country, Postcode = this.Postcode };
    }

    public void DisableValidation()
    {
        TypeDescriptor.RemoveProviderTransparent(metadataAddress, typeof(Address));
    }
    #endregion

}

Lets assume for simplicity's sake that AddressMetadata on 'House' has a [Required] attribute, though obviously I have regular expressions for postcode, etc. etc. too.

Lets assume I'm working in the same assembly so the internal modifier isn't important.

Now if I call:

Address stuff = new Address("", "", "", "", "", "", "");

then the validation kicks in (via SetAddress) no problem at all.

If I do:

Address stuff = new Address();
stuff.DisableValidation();
stuff.SetAddress("", "", "", "", "", "", "");

I expect the validation to be disabled.

Does that help anyone provide more information?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文