Everybody都知道IDictionary<TKey, TValue>表示键/值对的泛型集合,是键/值对的泛型集合的基接口,典型的应用就是字典类Dictionary,但清楚KeyedCollection<TKey, TItem>的应用吗,与IDictionary又有什么区别呢?
它提供集合键嵌入在值中的集合的抽象基类,是基于 IList<T> 泛型接口的集合与基于 IDictionary<T>泛型接口的集合之间的组合体,与基于 IList<T>泛型接口的集合一样,KeyedCollection<TKey, TItem>也是项的索引列表,与基于 IDictionary<TKey, TValue>泛型接口的集合一样,KeyedCollection<TKey, TItem> 包含与每个元素关联的一个键。
与字典不同,KeyedCollection<TKey, TItem>的元素不是键值对;相反整个元素是值,而键嵌入在值内,KeyedCollection<TKey, TItem>中的每个键必须是唯一的,键不能为 null引用。
应用实例:(以开源组件json.net的代码举例)
比如有这样一个类:
Code
using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
namespace JSON
{
public struct MemberMapping
{
private readonly string _mappingName;
private readonly MemberInfo _member;
private readonly bool _ignored;
private readonly bool _readable;
private readonly bool _writable;
public MemberMapping(string mappingName, MemberInfo member, bool ignored, bool readable, bool writable)
{
_mappingName = mappingName;
_member = member;
_ignored = ignored;
_readable = readable;
_writable = writable;
}
public string MappingName
{
get { return _mappingName; }
}
public MemberInfo Member
{
get { return _member; }
}
public bool Ignored
{
get { return _ignored; }
}
public bool Readable
{
get { return _readable; }
}
public bool Writable
{
get { return _writable; }
}
}
}
现在定义一个MemberMapping类的集合类,同时这个集合的每一项的值以键值对的形式存在(嵌入一个键值对),我们可以这样实现,
先定义一个派生KeyedCollection<TKey, TItem>的集合类:
Code
using System;
using System.Collections.Generic;
using System.Text;
using System.Collections.ObjectModel;
namespace JSON
{
public class MemberMappingCollection : KeyedCollection<string, MemberMapping>
{
protected override string GetKeyForItem(MemberMapping item)
{
return item.MappingName;
}
public void AddMapping(MemberMapping memberMapping)
{
if (Contains(memberMapping.MappingName))
{
// don't overwrite existing mapping with ignored mapping
if (memberMapping.Ignored)
return;
MemberMapping existingMemberMapping = this[memberMapping.MappingName];
if (!existingMemberMapping.Ignored)
{
throw new JsonSerializationException(
string.Format(
"A member with the name '{0}' already exists on {1}. Use the JsonPropertyAttribute to specify another name.",
memberMapping.MappingName, memberMapping.Member.DeclaringType));
}
else
{
// remove ignored mapping so it can be replaced in collection
Remove(existingMemberMapping);
}
}
Add(memberMapping);
}
}
}
这样一个元素值以键值对形式存在的集合就诞生了,下面就举例如何使用这样的一个集合类:
比如有一个Person类:
public class Person
{
public string Name
{
get;
set;
}
public int Age
{
get;
set;
}
public int Salary
{
get;
set;
}
}
//根据类型获取类的成员集合
private MemberMappingCollection CreateMemberMappings(Type objectType)
{
MemberInfo[] members = objectType.GetMembers();
foreach(MemberInfo member in members)
{
string mappedName;
MemberMapping memberMapping = new MemberMapping(member.Name, member, ignored, readable, writable);
memberMappings.AddMapping(memberMapping);
}
return memberMappings;
}
//用处
//这样随便传入一个类型便可获得这个类型的成员以键值对形式存在的集合
MemberMappingCollection memberMappings = CreateMemberMappings(typeof(Person));
(注释:memberMappings集合中的元素的值是MemberMapping实例)MemberMappong实例键值对形式,键:成员名称; 值:成员对象)