【IT168技术文档】
本文介绍NBear的接口式实体定义方式下的自定义实体属性和实体多根继承。本文中的介绍的内容及对应的代码同样包含于最新版本的NBear及其用户手册中。
最新版本的NBear中除了本文中提到的两个功能之外,还包括如下内容:
1)支持EntityFactory.CreateObject和CreateObjectList现在支持基于DataSet或IDataReader中的字段名称而不仅仅是原来的基于字段顺序的数据填充了;
2)Gateway.Save和Insert方法现在支持自动返回新插入的纪录的自增长ID字段了(当然,前提是,这个实体对应的表确实使用自增长主键字段)。
自定义实体属性
什么是CustomProperty呢?CustomProperty是一种可以为Entity添加的,不映射到数据表字段的,只读的,用于解析Clob或Blog属性的,自定义类型的属性。
简单的说,如果你的实体包含Clob或Blob大字段,而又想方便的直接读取大字段真正代表的内容,就可以给Entity定义CustomProperty,来封装对大字段内容的访问。
让我们用一个实例来说明:
假设有这样一个Entity:
public interface EntityWithCustomProperty : IEntity
{
[PrimaryKey]
int ID { get; }
string Name { get; set; }
string XmlServerConfig { get; set; }
string XmlContactConfig { get; set; }
[CustomProperty("XmlServerConfig", "XmlContactConfig")]
SampleCustomPropertyType SampleProperty { get; }
}
首先,这个属性是只读的(只有get,注意,必须设为只读,否则,运行时使用该Entity会报错),它的返回类型是一个自定义类型SampleCustomProperty,它的定义如下:
[Serializable]
public class SampleServerConfig
{
public string ServerAddress;
public int ServerPort;
}
[Serializable]
public class SampleContactConfig
{
public string WorkPhone;
public string HomePhone;
}
public class SampleCustomPropertyType : CustomPropertyType
{
public SampleServerConfig ServerConfig
{
get
{
return SerializeHelper.Deserialize<SampleServerConfig>(typeof(SampleServerConfig), (string)values[0]);
}
}
public SampleContactConfig ContactConfig
{
get
{
return SerializeHelper.Deserialize<SampleContactConfig>(typeof(SampleContactConfig), (string)values[1]);
}
}
public SampleCustomPropertyType(object[] inputValues) : base(inputValues)
{
}
}
这个类的内容很简单,它包含两个属性,分别也是两个自定义的config类。values[0]和values[1]分别是这两个config类的XML序列化文本。在这两个属性的get实现中,
只是简单地进行反序列化。
values是哪儿来的呢?它是定义于基类CustomPropertyType的一个protected字段。包含了构造函数传入的inputValues参数。
inputValues的值又是哪来的呢?换句话说,既然Entity只是一个接口,谁负责实例化Entity的SampleProperty属性,并传入SampleCustomProperty类的构造函函数需要的inputValues参数呢?
我们注意到,EntityWithCustomProperty.SampleProperty属性包含一个CustomPropertyAttribute修饰,它的参数XmlServerConfig和XmlContactConfig表示,名为这两个名称的属性的值,将会被Entity的实现类用来构造成一个obejct[]数组,传递给SampleCustomPropertyType的构造函数。
注意,NBear.Common.CustomPropertyAttribute的构造函数接受一个params string[]类型的参数,可以是任意数量的Property的名称。
那么,这样一个SampleProperty属性,到底有什么用呢?
让我们来看看测试代码:
[TestMethod]
public void TestCustomPropertyMethod()
{
//provided the entity obj's value is read from database
EntityWithCustomProperty obj = EntityFactory<EntityWithCustomProperty>.CreateObject();
SampleServerConfig sc = new SampleServerConfig();
sc.ServerAddress = "127.0.0.1";
sc.ServerPort = 8888;
obj.XmlServerConfig = SerializeHelper.Serialize(sc);
SampleContactConfig cc = new SampleContactConfig();
cc.WorkPhone = "110";
cc.HomePhone = "119";
obj.XmlContactConfig = SerializeHelper.Serialize(cc);
//now we can use Custom Property like following
Assert.AreEqual(obj.SampleProperty.ServerConfig.ServerAddress, "127.0.0.1");
Assert.AreEqual(obj.SampleProperty.ServerConfig.ServerPort, 8888);
Assert.AreEqual(obj.SampleProperty.ContactConfig.WorkPhone, "110");
Assert.AreEqual(obj.SampleProperty.ContactConfig.HomePhone, "119");
}
很显然,如果我们直接读取XmlServerConfig和XmlContactConfig属性,因为他们是XML,并不易于使用(XML也许还好,如果它是一组二进制压缩数据呢?)。但是如果我们调用SampleProperty属性,我们就能很方便的读取XML中的真实内容(XML被自动反序列化为SampleProperty属性实例中的值了)。
本文作者: