我的情况是这样的: 我正在使用 Entity Framework 的数据库优先方法在 Visual Studio 2013 上编写一个 MVC 网站。
EF 自动生成模型。但是我需要添加自定义属性(~NOT~ 必须用于数据验证,但也用于内部流程)并通过反射访问这些自定义属性。
假设我有
public partial class Application {
public int AppID {get; set;}
public string Name {get; set;}
//etc...
}
我尝试了以下方法:
• 在不同的文件上我继续部分类:
public partial class Application {
[MyAttributeOne]
public int AppID { get; set; }
[DataType(DataType.Text)]
[MyAttributeTwo]
public string Name { get; set; }
}
• 使用元数据类
public class ApplicationMetadata {
[MyAttributeOne]
public int SolutionID { get; set; }
[DataType(DataType.Text)]
[MyAttributeTwo]
public string Name { get; set; }
}
[MetadataType(typeof(ApplicationMetadata))]
public partial class Application { }
• 继承具有属性的类:
public class ApplicationMetadata {
[MyAttributeOne]
public int SolutionID { get; set; }
[DataType(DataType.Text)]
[MyAttributeTwo]
public string Name { get; set; }
}
public partial class Application : ApplicationMetadata { }
• 以及“Buddy 类”方法,我基本上采用前两种方法,但我使用“应用程序”类中的属性定义类。
我做错了什么吗?或者这根本不可能?
我需要能够使以下代码工作:
foreach (PropertyInfo propertyInfo in currentObject.GetType().GetProperties())
{
foreach (CustomAttributeData attrData in propertyInfo.GetCustomAttributesData())
{
if (typeof(attrData) == typeof(MyAttributeOne))
//stuff
else if (typeof(attrData) == typeof(MyAttributeTwo))
//different stuff
else
//yet more stuff
}
}
非常感谢您的关注! 问候。
最佳答案
好吧,这有点复杂,但相当简单。这也确实有点脑残,但它确实有效并且给了你足够的工作空间。让我们设置一些基础知识:
//A couple of custom attributes
public class MyAttributeOne : Attribute { }
public class MyAttributeTwo : Attribute { }
//A metadata class where we can use the custom attributes
public sealed class MyEntityMetadata
{
//This property has the same name as the class it is referring to
[MyAttributeOne]
public int SomeProperty { get; set; }
}
//And an entity class where we use System.ComponentModel.DataAnnotations.MetadataType
//to tell our function where the metadata is stored
[MetadataType(typeof(MyEntityMetadata))]
public class MyEntity
{
public int SomeProperty { get; set; }
}
好的,还在我身边吗?现在我们需要一个函数来以与您之前相同的方式处理属性:
public void DoStuff(object currentObject)
{
//Lets see if our entity class has associated metadata
var metaDataAttribute = currentObject.GetType()
.GetCustomAttributes()
.SingleOrDefault(a => a is MetadataTypeAttribute) as MetadataTypeAttribute;
PropertyInfo[] metaProperties = null;
//Cache the metadata properties here
if (metaDataAttribute != null)
{
metaProperties = metaDataAttribute.MetadataClassType.GetProperties();
}
//As before loop through each property...
foreach (PropertyInfo propertyInfo in currentObject.GetType().GetProperties())
{
//Refactored this out as it's called again later
ProcessAttributes(propertyInfo.GetCustomAttributes());
//Now check the metadata class
if (metaProperties != null)
{
//Look for a matching property in the metadata class
var metaPropertyInfo = metaProperties
.SingleOrDefault(p => p.Name == propertyInfo.Name);
if (metaPropertyInfo != null)
{
ProcessAttributes(metaPropertyInfo.GetCustomAttributes());
}
}
}
}
当然,这是处理属性的重构方法:
private void ProcessAttributes(IEnumerable<Attribute> attributes)
{
foreach (var attr in attributes)
{
if (attr is MyAttributeOne)
{
Console.WriteLine("MyAttributeOne found");
}
else if (attr is MyAttributeTwo)
{
Console.WriteLine("MyAttributeTwo found");
}
else
{
}
}
}
关于C# 使用 EF 访问 MVC 上的部分类的自定义属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39884773/