Databases Reference
In-Depth Information
[MetadataType(typeof(
IProduct
))]
public partial class Product :
IProduct
{
}
Notice that the Product class not only implements the
IProduct
interface, but also speci-
fies it as the metadata type. Unlike the untyped metadata class in the previous example,
the metadata interface has to declare the
ProductName
property of type
string
for it to
match its actual implementation in the real Product class. Should they ever get out of
sync, you get an immediate compiler error as opposed to an
InvalidOperationException
at runtime.
NOTE
Neither of the two approaches to metadata types discussed here is perfect. The
nested classes approach results in the best encapsulation; there are no additional
types that are introduced at the assembly level. This helps to reduce confusion and
makes metadata classes impossible to misuse. The interfaces approach makes main-
taining the metadata types easier but results in additional interface types introduced in
the data model assembly. The interfaces can be declared as internal, but they will still
be visible and possible to misuse in the data model assembly itself. In the end, the
decision on whether to use nested classes or interfaces for data annotations will prob-
ably depend on your personal taste.
Registering Metadata Provider with TypeDescriptor
If you try to compile and run the following code in a console application separate from a
Dynamic Data web application, you might be surprised to find that the
RequiredAttribute
applied to the
ProductName
property of the
Product
class using the metadata class is
completely ignored, and the
ValidateObject
method does not throw the
ValidationException
, as you would expect:
var product = new Product();
var context = new ValidationContext(product, null, null);
Validator.ValidateObject(product, context, true);
Behind the scenes, the
Validator
uses
TypeDescriptor
, a static class from the
System.ComponentModel
namespace, to determine the list of attributes applied to each
property of the object it needs to validate. The
MetadataTypeAttribute
applied to the
Product
class actually does not have any effect
unless it has been configured
for a specific
object or its entire class. Dynamic Data does this automatically for all entity classes during
context registration, but to perform validation in other types of applications, you need to
do this explicitly by calling
TypeDescriptor
's static
AddProviderTransparent
method and
passing it an instance of the
AssociatedMetadataTypeTypeDescriptionProvider
class as
shown here: