日期:2014-05-17  浏览次数:21075 次

C#中、自定义属性解决了什么问题?
namespace AttributeTest
{
    
    class PersionesAttribute : Attribute
    {
        public PersionesAttribute(string menumName, string guid)
        {
            MenuName = menumName;
            Guid = guid;
        }

        public string MenuName { get; set; }
        public string Guid { get; set; }
    }
}
如上、在为类、方法等定义自定义属性的意义是什么?
为什么要这么做?
这样做的优缺点是什么?
有没有其它的替代方法?
.net自定义属性

------解决方案--------------------
给类、方法打标记,供反射的时候检索、判断。

比如说,VS的Windows窗体设计器利用加在用户控件上的Attribute知道如何对属性分类,如何为某个特定类型的属性加载属性编辑器,甚至可以隐藏一些属性,不在属性列表中显示。
ASP.NET MVC利用Attribute得知一个控制器中哪些方法可以映射到URL作为动作方法,哪些方法则不是。
EF利用Attribute得知一个实体对象如何和数据库映射,比如一个字段是否是主键,是否允许为空,它映射到什么字段上。
C#编译器利用Attribute知道一个类型是否支持序列化、反序列化。

你也可以自己用Attribute增加你需要的标记,比如你写了一个通用的实体对象属性的拷贝代码,使用反射遍历和拷贝属性,但是你希望遇到某些特定的属性,使用特殊的拷贝方式,甚至忽略某些属性,那么你可以给这些属性定义一些Attribute,在你的拷贝的代码中检索和判断。

关于有没有替代方法的问题,我们知道Java就没有Attribute,那么你会看到,比如同样的功能,EF使用Attribute,类似功能的Java的框架(比如Hibernate),或者ASP.NET MVC vs Struts,它们使用和源代码分离的配置文件——也就是我们完全可以将这些标记信息记录在配置文件中,但是和Attribute相比,后者的缺点是显而易见的,不直观,不统一,需要专门学习,没有编译器的检查。当然Attribute也有局限,那就是它只能由编译器加载,所以相当于写死在程序中,不能在运行时修改、创建和删除一个对象的Attribute,也不能使用泛型作为Attribute,因为泛型类型是运行时产生的。
------解决方案--------------------
虽然官方也翻译为属性,但有一本书说为了区分还是翻译成 特性 比较好
1.意义就是为了更强大的描述(没有什么优缺点可以说,这个就像语法一样,所以也没有替代方法)
比如:你要描述一个类是可以序列化的
[Serializable]
public class YourClass

比如:你要描述一个方法是过期了,叫大家不要再使用了
[Obsolete("过期了")]
public void Method()

2.AOP实现(搜索AOP可以了解到优缺点和代替方法,)
[UserAuth]//在执行这个Action前,判断是否有权限访问
public ActionResult Index()




------解决方案--------------------
[Obsolete("过期了,请使用NewMethod")]
public void Method()

public void NewMethod()
------解决方案--------------------
属性可设置对外公开,外部访问这个类时,根据不同的属性获取不同的值,或者根据公用属性的设置,允许哪些属性或方法对外可以访问,哪些不能
------解决方案--------------------
在某些场景下,或许你需要让编译器认为PersionesAttribute是一个Attribute,而在接收方,或许Attribute包含的属性并不足够描述,所以你需要继承。
------解决方案--------------------
解决了在类型实例化之前的描述,告诉编译器这个类型可以干些什么事。对于未实例化的类型来说,没有任何信息可以通过类的对象来存储并传递,只能通过特性来告诉编译器。