编辑5.1. 简介
(Available in 1.0)
IObjectWrapper是Spring.NET核心类库的一个底层接口,一般情况下开发人员不会直接去使用它,但由于本文档是一份参考文档,我们认为还是应该对此核心接口稍作阐述。开发人员可以用这个接口来实现数据绑定,因为数据绑定恰好是IObjectWrapper要解决的问题。
顶部
编辑5.2. 使用IObjectWrapper接口管理对象
IObjectWrapper接口和ObjectWrapper类是Spring.Objects命名空间下的重要类型。 IObjectWrapper接口的功能包括(单个或成批的)设置和读取属性的值、获取属性的描述信息(即 System.Reflection.PropertyInfo类的实例)以及查询属性的可读/写性。IObjectWrapper支持嵌套属性,可以为任意深度的属性赋值。该接口一般不会在应用程序代码中直接使用,而是由Spring.NET框架内部的类使用,比如IObjectFactory的各个实现类就用到了这个接口。
IObjectWrapper的名字基本可以说明它的工作方式:将一个对象包装起来,再对其进行操作,比如读/写被包装对象的属性值等。
注意:如果不打算直接使用IObjectWrapper接口,那么本节的内容可以跳过不看。
顶部
编辑5.2.1. 读、写普通及嵌套的属性
IObjectWrapper接口中设置和读取属性值的方法分别是SetPropertyValue()和GetPropertyValue(),这两个方法都有很多重载,详细内容可参考API文档。
SetPropertyValue()和GetPropertyValue()方法可以用属性路径来查找属性。属性路径是一个表达式,实现了IObjectWrapper的类可以根据该路径查找被包装对象的属性,下面是一些例子...
表 5.1. 属性路径的例子| 路径 | 解释 |
|---|
| name | 表示被包装对象中名为name的属性。 |
| account.name | 表示被包装对象中account属性的name属性。 |
| account[2] | 表示被包装对象中account属性索引器的第3个元素。索引属性一般用于访问集合字段,也可以访问任何支持索引的类型。 |
我们来看一个使用IObjectWrapper读写对象属性的例子,先看下面两个类:
[C#]
public class Company
{
private string name;
private Employee managingDirector;
public string Name
{
get { return this.name; }
set { this.name = value; }
}
public Employee ManagingDirector
{
get { return this.managingDirector; }
set { this.managingDirector = value; }
}
}
[C#]
public class Employee
{
private string name;
private float salary;
public string Name
{
get { return this.name; }
set { this.name = value; }
}
public float Salary
{
get { return salary; }
set { this.salary = value; }
}
}
在下面的代码中,用IObjectWrapper通过属性名来读写被包装的Company和Employee对象的属性:
[C#]
Company c = new Company();
IObjectWrapper owComp = new ObjectWrapper(c);
// setting the company name...
owComp.SetPropertyValue("name", "Salina Inc.");
// can also be done like this...
PropertyValue v = new PropertyValue("name", "Salina Inc.");
owComp.SetPropertyValue(v);
// ok, let's create the director and bind it to the company...
Employee don = new Employee();
IObjectWrapper owDon = new ObjectWrapper(don);
owDon.SetPropertyValue("name", "Don Fabrizio");
owComp.SetPropertyValue("managingDirector", don);
// retrieving the salary of the ManagingDirector through the company
float salary = (float)owComp.GetPropertyValue("managingDirector.salary");
注意Spring.NET是遵循CLS(Common Language Specification,通用语言规范)的,任何要解析为属性、事件或类型的字符串都是大小写无关的。所以在上面的例子中,虽然C#是大小写敏感的,我们也可以用小写的"name"来设置Employee对象的Name属性。下面的例子(仍使用上面的类型)更能说明这个问题...
[C#]
// ok, let's create the director and bind it to the company...
Employee don = new Employee();
IObjectWrapper owDon = new ObjectWrapper(don);
owDon.SetPropertyValue("naMe", "Don Fabrizio");
owDon.GetPropertyValue("nAmE"); // gets "Don Fabrizio"
IObjectWrapper owComp = new ObjectWrapper(new Company());
owComp.SetPropertyValue("ManaGINGdirecToR", don);
owComp.SetPropertyValue("mANaGiNgdirector.salARY", 80000);
Console.WriteLine(don.Salary); // puts 80000
Spring.NET的这种大小写无关的处理方式是遵循CLS规范的,不是什么功能缺陷。如果您正好有这样一个类型,其中部分属性、事件或者方法仅能以大小写来区分,那么您就需要考虑重构代码了,因为一般说来都会认为这不是好的编码风格。
顶部
编辑5.2.2. 其它功能
除了上一小节讲到的功能,IObjectWrapper还有一些其它功能,虽然不值得单独花一小节来讲,不过您可能会比较感兴趣:
- 检测属性的可读性和可写性。可以用IsReadable()和IsWritable()方法检测某个属性是否可读或可写。
- 获取PropertyInfo实例。使用GetPropertyInfo(string)和GetPropertyInfos()方法,可以获取System.Reflection.PropertyInfo类的实例,如果需要访问被包装对象属性的元数据,可以用这两个方法。
顶部编辑5.3. 类型转换
如果已经用标准的.NET机制将一个类型转换器和某个类型关联了起来(看下面的代码),Spring.NET就会使用这个类型转换器进行类型转换。
[C#]
[TypeConverter (typeof (FooTypeConverter))]
public class Foo
{
}
Spring.Core中的很多类都用到了System.ComponentModel命名空间下的TypeConverter类,这些类“...可以用统一的方式来进行类型转换和普通值及子属性的访问。”。[4]
例如,我们可以用可读性较好的格式表示一个日期(比如1984年8月30日),也可以将它转换为原始的日期格式(或者)System.DateTime类型。在. NET中,通过为某个类型应用TypeConverterAttribute特性,可以为它指定类型转换器。Spring.NET则提供了另外几种关联类型转换器的方式。Spring.NET可以进行某些无法用标准方式完成的转换,比如,Spring.Core程序集中有一个类型转换器,可以将以逗号分隔的字符串转换为字符串数组。用Spring.NET注册了自定义类型转换器之后,IObjectWrapper接口就知道如何将某个值转换为指定类型了。
我们在IoC容器中配置对象的属性时,Spring.NET就在后台应用了TypeConverter。当用字符串值定义某个对象的属性(比如通过 XML定义来声明),且这个属性的类型是System.Type时,Spring.NET会尝试用RuntimeTypeConverter将字符串值转换为Type对象。下面这个例子就将字符串“Example.Xml.SAXParser”自动转换为了相应的Type对象:
<objects xmlns="http://www.springframework.net">
<object id="parserFactory" type="Example.XmlParserFactory, ExamplesLibrary"
destroy-method="Close">
<property name="ParserClass" value="Example.Xml.SAXParser, ExamplesLibrary"/>
</object>
</objects>
[C#]
public class XmlParserFactory
{
private Type parserClass;
public Type ParserClass
{
get { return this.parserClass; }
set { this.parserClass = value; }
}
public XmlParser GetParser ()
{
return Activator.CreateInstance (ParserClass);
}
}
顶部编辑5.3.1. 转换枚举类型
枚举类型的默认转换器是System.ComponentModel.EnumConverter,它会将枚举值的名字转换为对应的值。比如说, TestObject类有个FileMode枚举类型的属性,该枚举有个名为Create的值,那么这个类的对象就可以这么配置:
<object id="rod" type="Spring.Objects.TestObject, Spring.Core.Tests">
<property name="Name" value="Rod"/>
<property name="FileMode" value="Create"/>
</object>
顶部
编辑5.4. 内置类型转换器
Spring.NET预先注册了一部分自定义类型转换器(例如将以字符串表示的类型名转换为System.Type对象的转换器)。这些转换器都定义在Spring.Core程序集的Spring.Objects.TypeConverters命名空间下,如下表所示:
表 5.2. 内置类型转换器| 类型 | 解释 |
|---|
| RuntimeTypeConverter | 将字符串表示的类型名转换为实际的System.Type对象 |
| FileInfoConverter | 将字符串转换为System.IO.FileInfo对象 |
| StringArrayConverter | 将以逗号分隔的字符串列表转换为字符串数组,反之亦可 |
| UriConverter | 将字符串表示URI转换为实际的URI对象 |
| StreamConverter | 将Spring的IResource URI的字符串表示形式转换为InputStream对象 |
| ResourceConverter | 将用字符串表示的Spring IResource格式的URI转换为IResource对象 |
| ResourceManagerConverter | 将一个以逗号分隔的两段字符串(资源名,程序集名)转换为一个System.Resource.ResourceManager对象 |
| RGBColorConverter | 将以逗号分隔的红,绿,蓝值转换为System.Drawing.Color结构 |
Spring.NET会使用标准的.NET机制来解析对象的类型,这些机制包括但不限于:检查和应用程序相关的所有配置文件、检查GAC以及使用程序集探测机制等。
[4] 原文为“... provides a unified way of converting types of values to other types, as well as for accessing standard values and subproperties.”。有关自定义TypeConverter的详细内容可以参见MSDN网站,相关内容可以搜索Implementing a Type Converter。
顶部