[Spring.NET IoC] 之一:基本信息
Spring.NET 移植自著名的 Java 开源项目 —— Spring,借助于 .NET 强大的反射机制,甚至拥有比原 Java 版本更强大的功能。只是不知道什么原因,在 .NET 领域似乎没有多少热度,其影响力甚至不如 Castle。因准备在个人项目中使用 IoC,因此花些时间对 Spring.NET 和 Castle 都作一些了解,本文权作学习笔记。
Spring.NET 的宣传口号中有 "non-invasiveness. Quite simply" 的字样,表示是非入侵且易用的,当然作为一个IoC容器,这些都是最基本的特征。
在 Spring.NET IoC 中最核心的内容应该是 IObjectFactory、IApplicationContext、IObjectDefinition 这三个接口了。IObjectFactory 是核心容器接口,负责管理容器内的注入对象,而 IApplicationContext 则是 IObjectFactory 的继承,它扩展了一些功能。IObjectDefinition 是注入对象的定义接口,供 IObjectFactory / IApplicationContext 调用。
大多数时候我们会选择 IApplicationContext 接口的实现类来操控 Spring.NET IoC 容器。
1. Spring.Context.Support.ContextRegistry
将配置信息写入 app.config / web.config 时所使用该类。
2. Spring.Context.Support.XmlApplicationContext
使用独立的 xml 配置文件,或者使用多个 xml 配置文件时,使用该类。
3. Spring.Context.Support.StaticApplicationContext
直接在代码中装配容器时,使用该类。
当然,你还可以使用 Spring.Objects.Factory.Xml.XmlObjectFactory 等直接实现 IObjectFactory 的类型。
作为该篇的结束,写一个简单的 "Hello World" 尝试一下。
test.cs
2. 独立配置文件
springtest.xml
test.cs
建议使用独立的配置文件,应用程序配置文件已经被塞入太多内容了。Spring.NET 还支持很多高级的
配置文件功能,将在后面做进一步介绍。
Spring.NET 的宣传口号中有 "non-invasiveness. Quite simply" 的字样,表示是非入侵且易用的,当然作为一个IoC容器,这些都是最基本的特征。
在 Spring.NET IoC 中最核心的内容应该是 IObjectFactory、IApplicationContext、IObjectDefinition 这三个接口了。IObjectFactory 是核心容器接口,负责管理容器内的注入对象,而 IApplicationContext 则是 IObjectFactory 的继承,它扩展了一些功能。IObjectDefinition 是注入对象的定义接口,供 IObjectFactory / IApplicationContext 调用。
大多数时候我们会选择 IApplicationContext 接口的实现类来操控 Spring.NET IoC 容器。
1. Spring.Context.Support.ContextRegistry
将配置信息写入 app.config / web.config 时所使用该类。
2. Spring.Context.Support.XmlApplicationContext
使用独立的 xml 配置文件,或者使用多个 xml 配置文件时,使用该类。
3. Spring.Context.Support.StaticApplicationContext
直接在代码中装配容器时,使用该类。
当然,你还可以使用 Spring.Objects.Factory.Xml.XmlObjectFactory 等直接实现 IObjectFactory 的类型。
作为该篇的结束,写一个简单的 "Hello World" 尝试一下。
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using Spring.Core;
using Spring.Context;
using Spring.Context.Support;
namespace ConsoleApplication1.SpringNet
{
public class HelloWorld
{
public override string ToString()
{
return "Hello, World!";
}
}
public class Program
{
static void Main(string[] args)
{
StaticApplicationContext context = new StaticApplicationContext();
context.RegisterPrototype("HelloWorld", typeof(HelloWorld), null);
object o = context.GetObject("HelloWorld");
Console.WriteLine(o);
}
}
}
using System.Collections.Generic;
using System.Text;
using System.Threading;
using Spring.Core;
using Spring.Context;
using Spring.Context.Support;
namespace ConsoleApplication1.SpringNet
{
public class HelloWorld
{
public override string ToString()
{
return "Hello, World!";
}
}
public class Program
{
static void Main(string[] args)
{
StaticApplicationContext context = new StaticApplicationContext();
context.RegisterPrototype("HelloWorld", typeof(HelloWorld), null);
object o = context.GetObject("HelloWorld");
Console.WriteLine(o);
}
}
}
[Spring.NET IoC] 之二:配置文件
Spring.NET IoC 支持2种配置文件方式:
1. 应用程序配置文件
app.config / web.config
1. 应用程序配置文件
app.config / web.config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<sectionGroup name="spring">
<section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core"/>
<section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core" />
</sectionGroup>
</configSections>
<spring>
<context>
<resource uri="config://spring/objects"/>
</context>
<objects xmlns="http://www.springframework.net">
<object id="HelloWorld" type="ConsoleApplication1.SpringNet.HelloWorld, Learn.CUI" >
</object>
</objects>
</spring>
</configuration>
<configuration>
<configSections>
<sectionGroup name="spring">
<section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core"/>
<section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core" />
</sectionGroup>
</configSections>
<spring>
<context>
<resource uri="config://spring/objects"/>
</context>
<objects xmlns="http://www.springframework.net">
<object id="HelloWorld" type="ConsoleApplication1.SpringNet.HelloWorld, Learn.CUI" >
</object>
</objects>
</spring>
</configuration>
test.cs
IApplicationContext context = ContextRegistry.GetContext();
object o = context.GetObject("HelloWorld");
object o = context.GetObject("HelloWorld");
2. 独立配置文件
springtest.xml
<?xml version="1.0" encoding="utf-8"?>
<objects xmlns="http://www.springframework.net" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.net
http://www.springframework.net/xsd/spring-objects.xsd">
<object id="HelloWorld" type="ConsoleApplication1.SpringNet.HelloWorld, Learn.CUI">
</object>
</objects>
<objects xmlns="http://www.springframework.net" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.net
http://www.springframework.net/xsd/spring-objects.xsd">
<object id="HelloWorld" type="ConsoleApplication1.SpringNet.HelloWorld, Learn.CUI">
</object>
</objects>
test.cs
IApplicationContext context = new XmlApplicationContext(@"springtest.xml");
object o = context.GetObject("HelloWorld");
object o = context.GetObject("HelloWorld");
建议使用独立的配置文件,应用程序配置文件已经被塞入太多内容了。Spring.NET 还支持很多高级的
[Spring.NET IoC] 之三:获取对象
依照第二篇的配置文件,我们可以初步注入我们所需的类型。本篇将记录获取对象的不同方法。
1. 构造方法创建对象
这种方式最常见,大多数时候我们都会采取此方式获取对象。如果目标对象需要提供构造参数,我们也可以在配置文件中提供。
需要注意的是 Spring.NET IoC 缺省对象创建方式是 "Singleton",我们写个例子验证一下。
我们只需在配置文件中添加一个标记即可改变为非 Singleton 方式。
2. 静态工厂方法创建对象
我们提供另外一个 HelloWorld 类,该类型没有公用构造方法,只能通过静态方法创建对象。
对于这种方式,我们只需指定 "factory-method" 即可,需要注意的是所指定的方法必须是静态方法。
3. 实例工厂方法创建对象
修改上面的例子。在下面的代码中我们必须通过一个名为 Creator 的类才能创建 HelloWorld。
通过上面的配置文件我们知道,我们必须提供一个 Creator 的注入声明,同时要为 HelloWorld 指定创建者的 "factory-object" 和 "factory-method"。
4. 对象初始化方法
我们可以在配置文件中使用 "init-method" 指定类型构造方法以外的初始化方法。该方法会在对象构造方法之后被容器调用执行,以便我们完成一些初始化操作。
需要注意的是对于 Singleton 方式来说,初始化只会被执行一次,因为后续对象是直接从容器中拷贝引用而已。
5. 设置对象属性
除了在配置文件中提供构造参数外,我们还可以直接为对象属性赋值。
6. 设置类型参数
上面的例子我们注入的数据都是基本类型,对于自定义类型我们需要做些声明。下面的例子中 HelloWorld 需要 2 个构造参数,分别是一个自定义类型和 Type。
一定要注意,注入一个对象和一个 Type 的不同之处。
1. 构造方法创建对象
这种方式最常见,大多数时候我们都会采取此方式获取对象。如果目标对象需要提供构造参数,我们也可以在配置文件中提供。
<?xml version="1.0" encoding="utf-8"?>
<objects xmlns="http://www.springframework.net" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.net
http://www.springframework.net/xsd/spring-objects.xsd">
<object id="HelloWorld" type="ConsoleApplication1.SpringNet.HelloWorld, Learn.CUI">
<constructor-arg name="name" value="Tom" />
<constructor-arg name="age" value="234" />
</object>
</objects>
<objects xmlns="http://www.springframework.net" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.net
http://www.springframework.net/xsd/spring-objects.xsd">
<object id="HelloWorld" type="ConsoleApplication1.SpringNet.HelloWorld, Learn.CUI">
<constructor-arg name="name" value="Tom" />
<constructor-arg name="age" value="234" />
</object>
</objects>
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using Spring.Core;
using Spring.Context;
using Spring.Context.Support;
namespace ConsoleApplication1.SpringNet
{
public class HelloWorld
{
private string name;
private int age;
public HelloWorld(string name, int age)
{
this.name = name;
this.age = age;
}
public override string ToString()
{
return String.Format("Name={0}; Age={1}", name, age);
}
}
public class Program
{
static void Main(string[] args)
{
IApplicationContext context = new XmlApplicationContext(@"Config\Spring.xml");
object o = context.GetObject("HelloWorld");
Console.WriteLine(o);
}
}
}
using System.Collections.Generic;
using System.Text;
using System.Threading;
using Spring.Core;
using Spring.Context;
using Spring.Context.Support;
namespace ConsoleApplication1.SpringNet
{
public class HelloWorld
{
private string name;
private int age;
public HelloWorld(string name, int age)
{
this.name = name;
this.age = age;
}
public override string ToString()
{
return String.Format("Name={0}; Age={1}", name, age);
}
}
public class Program
{
static void Main(string[] args)
{
IApplicationContext context = new XmlApplicationContext(@"Config\Spring.xml");
object o = context.GetObject("HelloWorld");
Console.WriteLine(o);
}
}
}
需要注意的是 Spring.NET IoC 缺省对象创建方式是 "Singleton",我们写个例子验证一下。
object o = context.GetObject("HelloWorld");
object o2 = context.GetObject("HelloWorld");
Console.WriteLine(object.ReferenceEquals(o, o2)); // output: true
object o2 = context.GetObject("HelloWorld");
Console.WriteLine(object.ReferenceEquals(o, o2)); // output: true
我们只需在配置文件中添加一个标记即可改变为非 Singleton 方式。
<?xml version="1.0" encoding="utf-8"?>
<objects xmlns="http://www.springframework.net" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.net
http://www.springframework.net/xsd/spring-objects.xsd">
<object id="HelloWorld" type="ConsoleApplication1.SpringNet.HelloWorld, Learn.CUI" singleton="false">
<constructor-arg name="name" value="Tom" />
<constructor-arg name="age" value="234" />
</object>
</objects>
<objects xmlns="http://www.springframework.net" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.net
http://www.springframework.net/xsd/spring-objects.xsd">
<object id="HelloWorld" type="ConsoleApplication1.SpringNet.HelloWorld, Learn.CUI" singleton="false">
<constructor-arg name="name" value="Tom" />
<constructor-arg name="age" value="234" />
</object>
</objects>
2. 静态工厂方法创建对象
我们提供另外一个 HelloWorld 类,该类型没有公用构造方法,只能通过静态方法创建对象。
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using Spring.Core;
using Spring.Context;
using Spring.Context.Support;
namespace ConsoleApplication1.SpringNet
{
public class HelloWorld
{
private HelloWorld()
{
}
public static HelloWorld Create()
{
return new HelloWorld();
}
}
public class Program
{
static void Main()
{
IApplicationContext context = new XmlApplicationContext(@"Config\Spring.xml");
object o = context.GetObject("HelloWorld");
object o2 = context.GetObject("HelloWorld");
Console.WriteLine(object.ReferenceEquals(o, o2)); // output: true
}
}
}
using System.Collections.Generic;
using System.Text;
using System.Threading;
using Spring.Core;
using Spring.Context;
using Spring.Context.Support;
namespace ConsoleApplication1.SpringNet
{
public class HelloWorld
{
private HelloWorld()
{
}
public static HelloWorld Create()
{
return new HelloWorld();
}
}
public class Program
{
static void Main()
{
IApplicationContext context = new XmlApplicationContext(@"Config\Spring.xml");
object o = context.GetObject("HelloWorld");
object o2 = context.GetObject("HelloWorld");
Console.WriteLine(object.ReferenceEquals(o, o2)); // output: true
}
}
}
对于这种方式,我们只需指定 "factory-method" 即可,需要注意的是所指定的方法必须是静态方法。
<?xml version="1.0" encoding="utf-8"?>
<objects xmlns="http://www.springframework.net" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.net
http://www.springframework.net/xsd/spring-objects.xsd">
<object id="HelloWorld" type="ConsoleApplication1.SpringNet.HelloWorld, Learn.CUI" factory-method="Create">
</object>
</objects>
<objects xmlns="http://www.springframework.net" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.net
http://www.springframework.net/xsd/spring-objects.xsd">
<object id="HelloWorld" type="ConsoleApplication1.SpringNet.HelloWorld, Learn.CUI" factory-method="Create">
</object>
</objects>
3. 实例工厂方法创建对象
修改上面的例子。在下面的代码中我们必须通过一个名为 Creator 的类才能创建 HelloWorld。
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using Spring.Core;
using Spring.Context;
using Spring.Context.Support;
namespace ConsoleApplication1.SpringNet
{
public class Creator
{
public HelloWorld Create()
{
return new HelloWorld();
}
}
public class HelloWorld
{
internal HelloWorld()
{
}
}
public class Program
{
static void Main()
{
IApplicationContext context = new XmlApplicationContext(@"Config\Spring.xml");
object o = context.GetObject("HelloWorld");
object o2 = context.GetObject("HelloWorld");
Console.WriteLine(object.ReferenceEquals(o, o2)); // output: true
}
}
}
using System.Collections.Generic;
using System.Text;
using System.Threading;
using Spring.Core;
using Spring.Context;
using Spring.Context.Support;
namespace ConsoleApplication1.SpringNet
{
public class Creator
{
public HelloWorld Create()
{
return new HelloWorld();
}
}
public class HelloWorld
{
internal HelloWorld()
{
}
}
public class Program
{
static void Main()
{
IApplicationContext context = new XmlApplicationContext(@"Config\Spring.xml");
object o = context.GetObject("HelloWorld");
object o2 = context.GetObject("HelloWorld");
Console.WriteLine(object.ReferenceEquals(o, o2)); // output: true
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<objects xmlns="http://www.springframework.net" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.net
http://www.springframework.net/xsd/spring-objects.xsd">
<object id="HelloWorld" type="ConsoleApplication1.SpringNet.HelloWorld, Learn.CUI" factory-method="Create" factory-object="Creator" />
<object id="Creator" type="ConsoleApplication1.SpringNet.Creator, Learn.CUI" />
</objects>
<objects xmlns="http://www.springframework.net" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.net
http://www.springframework.net/xsd/spring-objects.xsd">
<object id="HelloWorld" type="ConsoleApplication1.SpringNet.HelloWorld, Learn.CUI" factory-method="Create" factory-object="Creator" />
<object id="Creator" type="ConsoleApplication1.SpringNet.Creator, Learn.CUI" />
</objects>
通过上面的配置文件我们知道,我们必须提供一个 Creator 的注入声明,同时要为 HelloWorld 指定创建者的 "factory-object" 和 "factory-method"。
4. 对象初始化方法
我们可以在配置文件中使用 "init-method" 指定类型构造方法以外的初始化方法。该方法会在对象构造方法之后被容器调用执行,以便我们完成一些初始化操作。
<?xml version="1.0" encoding="utf-8"?>
<objects xmlns="http://www.springframework.net" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.net
http://www.springframework.net/xsd/spring-objects.xsd">
<object id="HelloWorld" type="ConsoleApplication1.SpringNet.HelloWorld, Learn.CUI" init-method="Init" />
</objects>
<objects xmlns="http://www.springframework.net" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.net
http://www.springframework.net/xsd/spring-objects.xsd">
<object id="HelloWorld" type="ConsoleApplication1.SpringNet.HelloWorld, Learn.CUI" init-method="Init" />
</objects>
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using Spring.Core;
using Spring.Context;
using Spring.Context.Support;
namespace ConsoleApplication1.SpringNet
{
public class HelloWorld
{
public HelloWorld()
{
}
public void Init()
{
Console.WriteLine("Init...");
}
}
public class Program
{
static void Main()
{
IApplicationContext context = new XmlApplicationContext(@"Config\Spring.xml");
object o = context.GetObject("HelloWorld");
Console.WriteLine(o);
}
}
}
using System.Collections.Generic;
using System.Text;
using System.Threading;
using Spring.Core;
using Spring.Context;
using Spring.Context.Support;
namespace ConsoleApplication1.SpringNet
{
public class HelloWorld
{
public HelloWorld()
{
}
public void Init()
{
Console.WriteLine("Init...");
}
}
public class Program
{
static void Main()
{
IApplicationContext context = new XmlApplicationContext(@"Config\Spring.xml");
object o = context.GetObject("HelloWorld");
Console.WriteLine(o);
}
}
}
需要注意的是对于 Singleton 方式来说,初始化只会被执行一次,因为后续对象是直接从容器中拷贝引用而已。
5. 设置对象属性
除了在配置文件中提供构造参数外,我们还可以直接为对象属性赋值。
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using Spring.Core;
using Spring.Context;
using Spring.Context.Support;
namespace ConsoleApplication1.SpringNet
{
public class HelloWorld
{
public HelloWorld()
{
}
private string name;
public string Name
{
get { return name; }
set { name = value; }
}
public override string ToString()
{
return name;
}
}
public class Program
{
static void Main()
{
IApplicationContext context = new XmlApplicationContext(@"Config\Spring.xml");
object o = context.GetObject("HelloWorld");
Console.WriteLine(o);
}
}
}
using System.Collections.Generic;
using System.Text;
using System.Threading;
using Spring.Core;
using Spring.Context;
using Spring.Context.Support;
namespace ConsoleApplication1.SpringNet
{
public class HelloWorld
{
public HelloWorld()
{
}
private string name;
public string Name
{
get { return name; }
set { name = value; }
}
public override string ToString()
{
return name;
}
}
public class Program
{
static void Main()
{
IApplicationContext context = new XmlApplicationContext(@"Config\Spring.xml");
object o = context.GetObject("HelloWorld");
Console.WriteLine(o);
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<objects xmlns="http://www.springframework.net" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.net
http://www.springframework.net/xsd/spring-objects.xsd">
<object id="HelloWorld" type="ConsoleApplication1.SpringNet.HelloWorld, Learn.CUI">
<property name="Name" value="Tom" />
</object>
</objects>
<objects xmlns="http://www.springframework.net" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.net
http://www.springframework.net/xsd/spring-objects.xsd">
<object id="HelloWorld" type="ConsoleApplication1.SpringNet.HelloWorld, Learn.CUI">
<property name="Name" value="Tom" />
</object>
</objects>
6. 设置类型参数
上面的例子我们注入的数据都是基本类型,对于自定义类型我们需要做些声明。下面的例子中 HelloWorld 需要 2 个构造参数,分别是一个自定义类型和 Type。
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using Spring.Core;
using Spring.Context;
using Spring.Context.Support;
namespace ConsoleApplication1.SpringNet
{
public class MyData
{
public override string ToString()
{
return "MyData...";
}
}
public class HelloWorld
{
private MyData data;
public HelloWorld(MyData data, Type type)
{
this.data = data;
Console.WriteLine(type);
}
public override string ToString()
{
return data.ToString();
}
}
public class Program
{
static void Main()
{
IApplicationContext context = new XmlApplicationContext(@"Config\Spring.xml");
object o = context.GetObject("HelloWorld");
Console.WriteLine(o);
}
}
}
using System.Collections.Generic;
using System.Text;
using System.Threading;
using Spring.Core;
using Spring.Context;
using Spring.Context.Support;
namespace ConsoleApplication1.SpringNet
{
public class MyData
{
public override string ToString()
{
return "MyData...";
}
}
public class HelloWorld
{
private MyData data;
public HelloWorld(MyData data, Type type)
{
this.data = data;
Console.WriteLine(type);
}
public override string ToString()
{
return data.ToString();
}
}
public class Program
{
static void Main()
{
IApplicationContext context = new XmlApplicationContext(@"Config\Spring.xml");
object o = context.GetObject("HelloWorld");
Console.WriteLine(o);
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<objects xmlns="http://www.springframework.net" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.net
http://www.springframework.net/xsd/spring-objects.xsd">
<object id="HelloWorld" type="ConsoleApplication1.SpringNet.HelloWorld, Learn.CUI">
<constructor-arg name="data" ref="MyData" />
<constructor-arg name="type" value="ConsoleApplication1.SpringNet.MyData, Learn.CUI" />
</object>
<object id="MyData" type="ConsoleApplication1.SpringNet.MyData, Learn.CUI" />
</objects>
<objects xmlns="http://www.springframework.net" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.net
http://www.springframework.net/xsd/spring-objects.xsd">
<object id="HelloWorld" type="ConsoleApplication1.SpringNet.HelloWorld, Learn.CUI">
<constructor-arg name="data" ref="MyData" />
<constructor-arg name="type" value="ConsoleApplication1.SpringNet.MyData, Learn.CUI" />
</object>
<object id="MyData" type="ConsoleApplication1.SpringNet.MyData, Learn.CUI" />
</objects>
一定要注意,注入一个对象和一个 Type 的不同之处。
[Spring.NET IoC] 之四:配置补充
1. 别名
我们为 HelloWorld 创建了一个别名 HelloWorld2,我们同样可以通过 HelloWorld2 获取对象。请注意下面的测试代码输出结果。
2. 继承
下面的例子中,我们为 HelloWorld 添加了一个 "parent" 声明,该申明表示 HelloWorld 继承 test 的配置属性,包括构造参数和属性设置,但不包括 "singleton" 等。当然继承的仅仅是配置信息,而不是类型。
3. 内联
对于下面的配置文件,我们还可以改成内联方式。
修改结果
4. 空值
注意空值(null) 和空字符串("")不同。
<?xml version="1.0" encoding="utf-8"?>
<objects xmlns="http://www.springframework.net" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.net
http://www.springframework.net/xsd/spring-objects.xsd">
<object id="HelloWorld" type="ConsoleApplication1.SpringNet.HelloWorld, Learn.CUI" />
<alias alias="HelloWorld2" name="HelloWorld"/>
</objects>
<objects xmlns="http://www.springframework.net" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.net
http://www.springframework.net/xsd/spring-objects.xsd">
<object id="HelloWorld" type="ConsoleApplication1.SpringNet.HelloWorld, Learn.CUI" />
<alias alias="HelloWorld2" name="HelloWorld"/>
</objects>
我们为 HelloWorld 创建了一个别名 HelloWorld2,我们同样可以通过 HelloWorld2 获取对象。请注意下面的测试代码输出结果。
object o = context.GetObject("HelloWorld");
object o2 = context.GetObject("HelloWorld2");
Console.WriteLine(object.ReferenceEquals(o, o2)); // output: true
object o2 = context.GetObject("HelloWorld2");
Console.WriteLine(object.ReferenceEquals(o, o2)); // output: true
2. 继承
下面的例子中,我们为 HelloWorld 添加了一个 "parent" 声明,该申明表示 HelloWorld 继承 test 的配置属性,包括构造参数和属性设置,但不包括 "singleton" 等。当然继承的仅仅是配置信息,而不是类型。
<?xml version="1.0" encoding="utf-8"?>
<objects xmlns="http://www.springframework.net" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.net
http://www.springframework.net/xsd/spring-objects.xsd">
<object id="test" type="ConsoleApplication1.SpringNet.Test, Learn.CUI" singleton="false">
<constructor-arg name="s" value="abc..." />
</object>
<object id="HelloWorld" type="ConsoleApplication1.SpringNet.HelloWorld, Learn.CUI" parent="test" />
</objects>
<objects xmlns="http://www.springframework.net" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.net
http://www.springframework.net/xsd/spring-objects.xsd">
<object id="test" type="ConsoleApplication1.SpringNet.Test, Learn.CUI" singleton="false">
<constructor-arg name="s" value="abc..." />
</object>
<object id="HelloWorld" type="ConsoleApplication1.SpringNet.HelloWorld, Learn.CUI" parent="test" />
</objects>
3. 内联
对于下面的配置文件,我们还可以改成内联方式。
<?xml version="1.0" encoding="utf-8"?>
<objects xmlns="http://www.springframework.net" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.net
http://www.springframework.net/xsd/spring-objects.xsd">
<object id="HelloWorld" type="ConsoleApplication1.SpringNet.HelloWorld, Learn.CUI">
<constructor-arg name="data" ref="MyData" />
</object>
<object id="MyData" type="ConsoleApplication1.SpringNet.MyData, Learn.CUI" />
</objects>
<objects xmlns="http://www.springframework.net" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.net
http://www.springframework.net/xsd/spring-objects.xsd">
<object id="HelloWorld" type="ConsoleApplication1.SpringNet.HelloWorld, Learn.CUI">
<constructor-arg name="data" ref="MyData" />
</object>
<object id="MyData" type="ConsoleApplication1.SpringNet.MyData, Learn.CUI" />
</objects>
修改结果
<?xml version="1.0" encoding="utf-8"?>
<objects xmlns="http://www.springframework.net" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.net
http://www.springframework.net/xsd/spring-objects.xsd">
<object id="HelloWorld" type="ConsoleApplication1.SpringNet.HelloWorld, Learn.CUI">
<constructor-arg name="data">
<object type="ConsoleApplication1.SpringNet.MyData, Learn.CUI" />
</constructor-arg>
</object>
</objects>
<objects xmlns="http://www.springframework.net" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.net
http://www.springframework.net/xsd/spring-objects.xsd">
<object id="HelloWorld" type="ConsoleApplication1.SpringNet.HelloWorld, Learn.CUI">
<constructor-arg name="data">
<object type="ConsoleApplication1.SpringNet.MyData, Learn.CUI" />
</constructor-arg>
</object>
</objects>
4. 空值
注意空值(null) 和空字符串("")不同。
<?xml version="1.0" encoding="utf-8"?>
<objects xmlns="http://www.springframework.net" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.net
http://www.springframework.net/xsd/spring-objects.xsd">
<object id="HelloWorld" type="ConsoleApplication1.SpringNet.HelloWorld, Learn.CUI">
<constructor-arg name="s">
<null/>
</constructor-arg>
</object>
</objects>
<objects xmlns="http://www.springframework.net" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.net
http://www.springframework.net/xsd/spring-objects.xsd">
<object id="HelloWorld" type="ConsoleApplication1.SpringNet.HelloWorld, Learn.CUI">
<constructor-arg name="s">
<null/>
</constructor-arg>
</object>
</objects>
[Spring.NET IoC] 之五:列表参数
我们可以在配置文件中向构造方法或者属性注入列表型参数,诸如 Array、ArrayList、Hashtable 等。
1. IList
在 .NET Framework 中实现 IList 的主要是 Array、ArrayList。
<?xml version="1.0" encoding="utf-8"?>
<objects xmlns="http://www.springframework.net" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.net
http://www.springframework.net/xsd/spring-objects.xsd">
<object id="HelloWorld" type="ConsoleApplication1.SpringNet.HelloWorld, Learn.CUI">
<constructor-arg name="list">
<list>
<value>1</value>
<value>2</value>
<value>3</value>
<value>4</value>
</list>
</constructor-arg>
</object>
</objects>
<objects xmlns="http://www.springframework.net" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.net
http://www.springframework.net/xsd/spring-objects.xsd">
<object id="HelloWorld" type="ConsoleApplication1.SpringNet.HelloWorld, Learn.CUI">
<constructor-arg name="list">
<list>
<value>1</value>
<value>2</value>
<value>3</value>
<value>4</value>
</list>
</constructor-arg>
</object>
</objects>
public class HelloWorld
{
public HelloWorld(IList list)
{
Console.WriteLine(list); // output: ArrayList
foreach (object o in list)
Console.WriteLine(o);
}
}
{
public HelloWorld(IList list)
{
Console.WriteLine(list); // output: ArrayList
foreach (object o in list)
Console.WriteLine(o);
}
}
我们会发现 Spring.NET IoC 缺省使用 ArrayList 来实现 IList 列表参数。
2. IDictionary
实现 IDictionary 的最常用类型是 Hashtable。
<?xml version="1.0" encoding="utf-8"?>
<objects xmlns="http://www.springframework.net" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.net
http://www.springframework.net/xsd/spring-objects.xsd">
<object id="HelloWorld" type="ConsoleApplication1.SpringNet.HelloWorld, Learn.CUI">
<constructor-arg name="dict">
<dictionary>
<entry key="1" value="a" />
<entry key="2" value="b" />
<entry key="3" value="c" />
<entry key="4" value="d" />
</dictionary>
</constructor-arg>
</object>
</objects>
<objects xmlns="http://www.springframework.net" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.net
http://www.springframework.net/xsd/spring-objects.xsd">
<object id="HelloWorld" type="ConsoleApplication1.SpringNet.HelloWorld, Learn.CUI">
<constructor-arg name="dict">
<dictionary>
<entry key="1" value="a" />
<entry key="2" value="b" />
<entry key="3" value="c" />
<entry key="4" value="d" />
</dictionary>
</constructor-arg>
</object>
</objects>
public class HelloWorld
{
public HelloWorld(IDictionary dict)
{
Console.WriteLine(dict); // output:System.Collections.Specialized.HybridDictionary
foreach (object o in dict.Keys)
{
Console.WriteLine("{0}={1}", o, dict[o]);
}
}
}
{
public HelloWorld(IDictionary dict)
{
Console.WriteLine(dict); // output:System.Collections.Specialized.HybridDictionary
foreach (object o in dict.Keys)
{
Console.WriteLine("{0}={1}", o, dict[o]);
}
}
}
看看 System.Collections.Specialized.HybridDictionary 的MSDN说明
在集合较小时,使用 ListDictionary 来实现 IDictionary,然后当集合变大时,切换到 Hashtable。
建议将该类用于字典中的元素数量未知的情况。它利用了 ListDictionary 处理小集合时性能改善的优点,同时也可灵活地切换到处理较大集合时能力比 ListDictionary 更好的 Hashtable。
如果集合的初始大小大于 ListDictionary 的最佳大小,那么集合立即存储在 Hashtable 中,以避免将元素从 ListDictionary 复制到 Hashtable 产生的系统开销。