问题
I have a problem attaching metadata class to ADO.NET entity data model generated classes. According to the following links...
http://blogs.microsoft.co.il/blogs/gilf/archive/2011/01/20/adding-metadata-to-entities-in-the-data-model.aspx
http://msdn.microsoft.com/en-us/library/cc679243.aspx
http://goneale.com/2009/03/04/using-metadatatype-attribute-with-aspnet-mvc-xval-validation-framework/
http://davidhayden.com/blog/dave/archive/2008/01/06/ASPNETDynamicDataTutorialBuddyMetadataProviderCustomMetadataProviders.aspx
http://davidhayden.com/blog/dave/archive/2008/05/15/DynamicDataWebsitesScaffoldTableScaffoldColumnAttributes.aspx
I created a metadata class to add some Attributes to properties. I could add this attributes to properties in generated classes and It works but I wanted to avoid loosing this attributes every time I have to update and recreate my ADO.NET entity data model.
My question is, what am I doing wrong ? Why in runtime properties does not have my custom attributes ?
This is a part of generated data class
[EdmEntityTypeAttribute(NamespaceName="HelpMeHowModel", Name="Article")]
[Serializable()]
[DataContractAttribute(IsReference=true)]
[MetadataType(typeof(ArticleMetaData))]
public partial class Article : EntityObject
{
#region Primitive Properties
/// <summary>
/// No Metadata Documentation available.
/// </summary>
[EdmScalarPropertyAttribute(EntityKeyProperty=false, IsNullable=false)]
[DataMemberAttribute()]
public global::System.Boolean IsPublished
{
get
{
return _IsPublished;
}
set
{
OnIsPublishedChanging(value);
ReportPropertyChanging("IsPublished");
_IsPublished = StructuralObject.SetValidValue(value);
ReportPropertyChanged("IsPublished");
OnIsPublishedChanged();
}
}
private global::System.Boolean _IsPublished;
partial void OnIsPublishedChanging(global::System.Boolean value);
partial void OnIsPublishedChanged();
...
.. and this is my metadata class
public class ArticleMetaData
{
#region Primitive Properties
[BoolFunction(BoolFunction.ThreeStateRadioButton)]
public global::System.Boolean IsPublished { get; set; }
回答1:
For everybody looking for the solution for the same problem...
Adding custom attributes to partial MetadataType class is possible and it works but there is a little problem.
Using
PropertyInfo pi;
pi.GetCustomAttributes(...)
will get the Attributes from the main class only and not from the class used as MetadataType.
Based on solution explained here
Attribute.IsDefined doesn't see attributes applied with MetadataType class
I created two extension methods for PropertyInfo class to get all attributes.
namespace FAIN.Framework.Commons
{
public static class PropertyInfoEx
{
public static object[] GetAllCustomAttributes(this PropertyInfo pi, bool inherit)
{
return GetAllCustomAttributes(pi, null, inherit);
}
/// <summary>
/// Get Custom Attributes + attributes added in MetadataType
/// </summary>
/// <param name="pi"></param>
/// <param name="attributeType"></param>
/// <param name="inherit"></param>
/// <returns></returns>
public static object[] GetAllCustomAttributes(this PropertyInfo pi, Type attributeType, bool inherit)
{
if (pi == null) return null;
List<object> allAttributes = new List<object>();
object[] attributes = null;
if (attributeType != null)
{
attributes = pi.GetCustomAttributes(attributeType, inherit);
}
else
{
attributes = pi.GetCustomAttributes(inherit);
}
allAttributes.AddRange(attributes);
// search all the Metadata of the class declaring the property to get all CustomAttributes if there are any
MetadataTypeAttribute[] metadataTypes = pi.DeclaringType.GetCustomAttributes(typeof(MetadataTypeAttribute), true).OfType<MetadataTypeAttribute>().ToArray();
foreach (MetadataTypeAttribute metadata in metadataTypes)
{
if (metadata != null)
{
PropertyInfo[] properties = metadata.MetadataClassType.GetProperties();
PropertyInfo propertyInfo = properties.Where(p => p.Name == pi.Name).FirstOrDefault();
if (propertyInfo != null)
{
if (attributeType != null)
{
attributes = propertyInfo.GetCustomAttributes(attributeType, inherit);
}
else
{
attributes = propertyInfo.GetCustomAttributes(inherit);
}
allAttributes.AddRange(attributes);
}
}
}
return allAttributes.ToArray();
}
}
}
来源:https://stackoverflow.com/questions/7868230/attaching-metadata-class-to-ado-net-entity-data-model-classes