我的搜索一直只提供解释如何使用和将属性应用于类的指南.我想学习如何创建自己的属性类以及它们如何工作的机制.
属性类是如何实例化的? 它们在应用它们的类被实例化时是否被实例化?是否为实例化它应用于的每个类实例化?例如,如果我将SerializableAttribute类应用于MyData类,并且我实例化5个MyData实例,那么在幕后会创建5个SerializbleAttribute类的实例吗?或者只有一个实例在所有实例之间共享?
属性类实例如何访问与之关联的类? SerializableAttribute类如何访问它应用的类,以便它可以序列化它的数据?它是否具有某种SerializableAttribute.ThisIsTheInstanceIAmAppliedTo属性?:)或者它是否反向工作,每当我序列化某些东西时,我传递MyClass实例的Serialize函数将反射性地通过属性并找到SerialiableAttribute实例?
Art*_*aru 35
我以前没有在日常工作中使用属性,但我已经读过它们了.我也做了一些测试,以支持我在这里说的话.如果我在任何地方都错了 - 随时告诉我这个:)
据我所知,属性不是常规类.当您创建应用它们的对象时,它们不会被实例化,而不是一个静态实例,而不是每个对象实例1.他们也没有访问他们应用的类.
相反,它们就像类的属性(属性?:P).不像.NET类属性,更像是"玻璃的一个属性是透明度"的属性.您可以检查哪些属性从反射应用于类,然后相应地对其进行操作.它们本质上是附加到类定义的元数据,而不是该类型的对象.
您可以尝试获取类,方法,属性等的属性列表.当您获得这些属性的列表时 - 这是它们将被实例化的位置.然后,您可以对这些属性中的数据进行操作.
例如Linq表,属性上有属性,用于定义它们引用的表/列.但是这些类不使用这些属性.相反,DataContext将在将linq表达式树转换为SQL代码时检查这些对象的属性.
现在有一些真实的例子..我在LinqPad中运行了这些,所以不要担心奇怪的Dump()方法.我用Console.WriteLine替换它,使代码更容易理解为不知道它的人:)
void Main()
{
Console.WriteLine("before class constructor");
var test = new TestClass();
Console.WriteLine("after class constructor");
var attrs = Attribute.GetCustomAttributes(test.GetType()).Dump();
foreach(var attr in attrs)
if (attr is TestClassAttribute)
Console.WriteLine(attr.ToString());
}
public class TestClassAttribute : Attribute
{
public TestClassAttribute()
{
DefaultDescription = "hello";
Console.WriteLine("I am here. I'm the attribute constructor!");
}
public String CustomDescription {get;set;}
public String DefaultDescription{get;set;}
public override String ToString()
{
return String.Format("Custom: {0}; Default: {1}", CustomDescription, DefaultDescription);
}
}
[Serializable]
[TestClass(CustomDescription="custm")]
public class TestClass
{
public int Foo {get;set;}
}
Run Code Online (Sandbox Code Playgroud)
此方法的控制台结果是:
before class constructor
after class constructor
I am here. I'm the attribute constructor!
Custom: custm; Default: hello
Run Code Online (Sandbox Code Playgroud)
并Attribute.GetCustomAttributes(test.GetType())返回此数组:(该表显示所有条目的所有可用列..所以不,Serializable属性没有这些属性:))
还有其他问题吗?随意问!
UPD: 我见过你问过一个问题:为什么要用它们?作为一个例子,我将告诉你有关XML-RPC.NET库的信息.您可以使用表示xml-rpc方法的方法创建XML-RPC服务类.现在最重要的是:在XmlRpc中,方法名称可以包含一些特殊字符,如点.因此,您可以使用flexlabs.ProcessTask()xml rpc方法.
您可以按如下方式定义此类:
[XmlRpcMethod("flexlabs.ProcessTask")]
public int ProcessTask_MyCustomName_BecauseILikeIt();
Run Code Online (Sandbox Code Playgroud)
这允许我以我喜欢的方式命名方法,同时仍然使用公共名称.
Chr*_*lor 16
属性本质上是可以附加到代码的各个部分的元数据.然后,该元数据可以是interogate并影响某些操作的行为.
属性几乎可以应用于代码的每个方面.例如,属性可以在程序集级别关联,例如AssemblyVersion和AssemblyFileVersion属性,这些属性控制与程序集关联的版本号.
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
Run Code Online (Sandbox Code Playgroud)
然后,可以将Serializable属性应用于类型声明,以将该类型标记为支持序列化.事实上,这个属性在CLR中具有特殊含义,实际上直接作为特殊指令存储在IL中的类型中,这被优化为存储为位标志,可以更有效地处理,有一些属性这种性质,称为伪自定义属性.
还有其他属性可以应用于方法,属性,字段,枚举,返回值等.您可以通过查看此链接来了解可以应用属性的可能目标 http://msdn.microsoft.com/en -us /库/ system.attributetargets(VS.90)的.aspx
除此之外,您还可以定义自己的自定义属性,然后将其应用于属性所针对的适用目标.然后在运行时,您的代码可以反映自定义属性中包含的值并采取适当的操作.
对于一个相当天真的例子,这仅仅是为了示例:)您可能想要编写一个持久性引擎,它将自动将Classes映射到数据库中的表,并将Class的属性映射到表列.您可以从定义两个自定义属性开始
TableMappingAttribute
ColumnMappingAttribute
Run Code Online (Sandbox Code Playgroud)
然后您可以将其应用于您的类,例如我们有一个Person类
[TableMapping("People")]
public class Person
{
[ColumnMapping("fname")]
public string FirstName {get; set;}
[ColumnMapping("lname")]
public string LastName {get; set;}
}
Run Code Online (Sandbox Code Playgroud)
当编译时,除了编译器发出自定义属性定义的附加元数据这一事实外,其他几乎没有受到影响.但是,您现在可以编写一个PersistanceManager,它可以动态检查Person类实例的属性,并将数据插入People表,将FirstName属性中的数据映射到fname列,将LastName属性映射到lname列.
至于有关属性实例的问题,不会为类的每个实例创建属性的实例.People的所有实例将共享TableMappingAttribute和ColumnMappingAttributes的相同实例.实际上,只有在第一次实际查询属性时才会创建属性实例.
是的,它们使用您提供的参数进行实例化.
该属性不"访问"该类.该属性附加到反射数据中的类'/ property的属性列表中.
[Serializable]
public class MyFancyClass
{ ... }
// Somewhere Else:
public void function()
{
Type t = typeof(MyFancyClass);
var attributes = t.GetCustomAttributes(true);
if (attributes.Count(p => p is SerializableAttribute) > 0)
{
// This class is serializable, let's do something with it!
}
}
Run Code Online (Sandbox Code Playgroud)
可以认为属性是post-it附加到类或方法定义(嵌入在程序集元数据中).
然后,您可以通过反射接受这些类型的处理器/运行器/检查器模块,查找这些类型并以不同方式处理它们.这称为声明性编程.您声明了一些行为,而不是在类型中为它们编写代码.
您可能希望在MSDN上运行本教程,其中包含大部分问题以及最后的示例.虽然他们可以提取一个名为
Audit(Type anyType);而不是复制该代码的方法.示例通过检查属性来"打印信息"..但您可以以同样的方式执行任何操作.
| 归档时间: |
|
| 查看次数: |
22915 次 |
| 最近记录: |