摘一段模式的说明, F#的: msdn是这么描述它的:“模式”是用于转换输入数据的规则。模式将在整个 F# 语言中使用,采用多种方式将数据与一个或多个逻辑结构进行比较、将数据分解为各个构成部分,或从数据中提取信息。
模式匹配自有其定义,同时也有很多种类,这里针对相对复杂的【结构比较】和【数据抽取】进行处理(有时候也叫类型检查与转换)。
直白点说,就是“检查下某个对象,看看是否有我们感兴趣的属性成员,如果有就取出这些成员值供后续使用”。
1、结构比较
考察如下对象
code 01
var o = new
{
a = 2,
b = 3,
d = 0,
c = new
{
a1 = 7,
b1 = 2,
e = new
{
name = "aaa",
Id = 0
}
}
};
当我们明确知道其具体类型时,可以通过属性访问获取相关值,
code 02
int r1=o.a; int r2=o.c.a1; string r3=o.c.e.name;
但是,当 类型不明确 时,比如:
code 03
method1(object obj)
在method1中,如何快速方便的获取其相关属性值?
首先,我们知道问题的出现是因为“类型不明确”,那么我们要做的第一件是就是还原类型信息;
在还原类型信息之前,首先要把我们想获取的信息描述出来,以 code 02 为例,
1、希望o上有一个名为a的属性,类型int
2、希望o上有一个名为c的属性,同时c上有一个名为a1的属性, 类型int
3、希望o上有一个名为c的属性,同时c上有一个名为e的属性,同时e上有一个名为name的属性 类型string
。。。。。。
不难发现,a、我们要描述的类型信息不必要与原类型一致,仅表示出期望得到的部分即可;
b、要描述的类型信息中能正确表达层级关系
c、要能够描述所有类型的属性成员
d、明确知道期望的类型信息
e、最好使用语言环境中直接提供的技术手段
综合以上,这里使用匿名对象进行类型描述,简单而且能同时满足以上5点。
code 04
var typeinfo = new
{
a = 3,//default(int)
c = new
{
a1 = 1,
e = new
{
name = default(string)
}
}
};
注意:类型描述时属性值没有意义,一般可以用default(type),这里使用值是为了后面比对结果。
有了类型描述后,进行类型检查就变的相对简单了,我们以类型描述信息为基准,逐个检查目标对象上有无对应的成员即可。
直接使用反射就可以了。
code 05
if ( pi.Name==npi.Name&& pi.PropertyType == npi.PropertyType)
{
return true.Result(new GetValue(o => npi.Getter(o)));//扩展方法等见code 06
}
code 06
public struct Result<T> { public bool OK; public T Value; public Result(bool ok, T resultOrReason) { this.OK = ok; this.Value = resultOrReason; } public static implicit operator Result<T>(bool value) { return new Result<T>(value, default(T)); } public static explicit operator bool(Result<T> value) { return value.OK; } public static bool operator ==(Result<T> a, Result<T> b) { return a.Equals(b); } public static bool operator !=(Result<T> a, Result<T> b) { return !a.Equals(b); } public override bool Equals(object obj) { var r = (Result<T>)obj; return this.OK == r.OK && object.Equals(this.Value, r.Value); } public override int GetHashCode() { return this.OK.GetHashCode() + (this.Value == null ? 0 : this.Value.GetHashCode()); } }