一年以来我最好的创意
从Kanas.Net 1.0开始,我对元数据的处理都是这样的:
TypeBroker:收集与实体类型相关的元数据信息,包括反射信息和映射信息;
PropertyBroker:收集与实体类型的属性相关的元数据信息,包括反射信息和映射信息。
这应该是必须经历的一步,是整个环境上下文信息中最重要的一部分。
在业务层很难避免对实体元数据信息的操作,例如定位实体类或者定位实体属性。
实体类型的问题还比较好办,毕竟在C#下可以使用typeof运算符。实体属性就比较麻烦了。
public abstract class Entity
{
intern Entity(Type entityType)
{
if (entityType != null)
{
if (typeof(BizObject).IsAssignableFrom(entityType))
{
_Type = TypeBroker.Types[entityType];
}
else
{
throw new ArgumentException("指定的类型不是实体类型", "entityType");
}
}
else
{
throw new ArgumentException("尚未指定实体类型", "entityType");
}
}

protected TypeBroker _Type;

protected PropertyBroker PropertyOf(int propertyindex)
{
PropertyBrokerCollection properties = _Type.Properties;
if (properties.Count > propertyIndex && 0 <= propertyIndex)
{
return properties[propertyIndex];
}
else
{
throw new ArgumentException("指定的属性序号无效", "propertyIndex");
}
}

private static Entity_Pet _Pet = new Entity_Pet();
public static Entity_Pet Pet
{
get
{
return _Pet;
}
}

private static Entity_Cat _Cat = new Entity_Cat();
public static Entity_Cat Cat
{
get
{
return _Cat;
}
}

public static implicit operator TypeBroker(Entity entity)
{
return entity._Type;
}
}

public class Entity_Pet : Entity
{
intern Entity_Pet() : base(typeof(Pet))
{
}

intern Entity_Cat(Type entityType) : base(entityType)
{
}

public PropertyBroker ID
{
get
{
return PropertyOf(typeof(Cat), 0);
}
}

public PropertyBroker Name
{
get
{
return PropertyOf(typeof(Cat), 1);
}
}
}

public class Entity_Cat : Entity_Pet
{
intern Entity_Cat() : base(typeof(Cat))
{
}

public PropertyBroker Color
{
get
{
return PropertyOf(typeof(Cat), 2);
}
}
}以上示例代码包含以下语义:
Entity.Pet表示宠物实体;Entity.Cat表示猫实体;
Entity.Pet.ID表示宠物的标识属性,Entity.Pet.Name表示宠物的名称属性;
Entity.Cat.ID表示猫的标识属性,Entity.Cat.Name表示猫的名称属性,Entity.Cat.Color表示猫的颜色属性。
于是,以上Hibernate实现检索的代码在我这里变成这样了:
StringConstraint.By(Entity.Cat.Name).Like("Frantz@")
在IDE环境下,敲入“Entity.”后会弹出所有实体类型名称;敲入“Entity.Cat.”后会弹出Cat这个实体类型所有的属性。如果你愿意在Entity的Cat静态属性上加上summary注释,还会提示实体类型的概念名呢!
TypeBroker:收集与实体类型相关的元数据信息,包括反射信息和映射信息;
PropertyBroker:收集与实体类型的属性相关的元数据信息,包括反射信息和映射信息。
这应该是必须经历的一步,是整个环境上下文信息中最重要的一部分。
在业务层很难避免对实体元数据信息的操作,例如定位实体类或者定位实体属性。
实体类型的问题还比较好办,毕竟在C#下可以使用typeof运算符。实体属性就比较麻烦了。
以往采用三种方式:
- 实体类型+属性序号,如:(typeof(Cat), 2)
- 实体类型+属性名称,如:(typeof(Cat), "Name")
- 属性全名称,如:("Cat.Name")
显然,以上三种方式都不够优雅。
看看Hibernate如何处理:
List cats = sess.createCriteria(Cat.class)
.add( Expression.like("name", "Fritz%") )
从Cat实体中检索名称含Fritz的实例集合,和我的方法二一样。
注意到那个"name",不仅需要开发者记住对Cat的name属性的命名,而且还逃过了设计期的类型检查,所有的错误必须到运行期才知道。
现在我在实体信息之外加了一个元数据词典,解决了这个问题。因为所有的实体类型的源代码都是工具生成的,所以再顺便生成一个元数据词典代价低廉。
具体实现是这样的:
定义实现一个抽象类:Entity
为每个实体类都建立一个词典类,继承自Entity或者Entity的派生类,每个类都指向相应的实体类型。例如名称为Entity_User的类型指向User实体。
在每个嵌套类型中为对应的实体类的每个属性定义一个对应的属性,该属性的名称为对应实体属性的名称,其值为对应属性的元数据。
在Entity类中为每个嵌套类定义一个私有的静态实例,并通过只读的静态属性暴露该静态实例。
这是示例代码:
public abstract class Entity
{
intern Entity(Type entityType)
{
if (entityType != null)
{
if (typeof(BizObject).IsAssignableFrom(entityType))
{
_Type = TypeBroker.Types[entityType];
}
else
{
throw new ArgumentException("指定的类型不是实体类型", "entityType");
}
}
else
{
throw new ArgumentException("尚未指定实体类型", "entityType");
}
}
protected TypeBroker _Type;
protected PropertyBroker PropertyOf(int propertyindex)
{
PropertyBrokerCollection properties = _Type.Properties;
if (properties.Count > propertyIndex && 0 <= propertyIndex)
{
return properties[propertyIndex];
}
else
{
throw new ArgumentException("指定的属性序号无效", "propertyIndex");
}
}
private static Entity_Pet _Pet = new Entity_Pet();
public static Entity_Pet Pet
{
get
{
return _Pet;
}
}
private static Entity_Cat _Cat = new Entity_Cat();
public static Entity_Cat Cat
{
get
{
return _Cat;
}
}
public static implicit operator TypeBroker(Entity entity)
{
return entity._Type;
}
}
public class Entity_Pet : Entity
{
intern Entity_Pet() : base(typeof(Pet))
{
}
intern Entity_Cat(Type entityType) : base(entityType)
{
}
public PropertyBroker ID
{
get
{
return PropertyOf(typeof(Cat), 0);
}
}
public PropertyBroker Name
{
get
{
return PropertyOf(typeof(Cat), 1);
}
}
}
public class Entity_Cat : Entity_Pet
{
intern Entity_Cat() : base(typeof(Cat))
{
}
public PropertyBroker Color
{
get
{
return PropertyOf(typeof(Cat), 2);
}
}
}Entity.Pet表示宠物实体;Entity.Cat表示猫实体;
Entity.Pet.ID表示宠物的标识属性,Entity.Pet.Name表示宠物的名称属性;
Entity.Cat.ID表示猫的标识属性,Entity.Cat.Name表示猫的名称属性,Entity.Cat.Color表示猫的颜色属性。
于是,以上Hibernate实现检索的代码在我这里变成这样了:
StringConstraint.By(Entity.Cat.Name).Like("Frantz@")
在IDE环境下,敲入“Entity.”后会弹出所有实体类型名称;敲入“Entity.Cat.”后会弹出Cat这个实体类型所有的属性。如果你愿意在Entity的Cat静态属性上加上summary注释,还会提示实体类型的概念名呢!


浙公网安备 33010602011771号