如何在 Sitecore 方面实现对象集合?
How can I implement collections of objects in a Sitecore facet?
This article 似乎暗示这是可能的,但似乎跳过了集合本身的关键实现。它列出了粗略的结构:
public interface ICoordinate : IElement
{
float Longitude { get; set; }
float Latitude { get; set; }
}
public interface IPlace : IElement
{
string Description { get; set; }
ICoordinate Coordinate { get; }
}
public interface IPlaces : IFacet
{
IElementDictionary<IPlace> Places { get; }
}
正是我需要的对象集合。那么我该如何实现呢?
[Serializable]
internal class Coordinate : Element, ICoordinate
{
private const string LONGITUDE = "Longitude";
private const string LATITUDE = "Latitude";
public float Longitude
{
get
{
return this.GetAttribute<float>( LONGITUDE );
}
set
{
this.SetAttribute( LONGITUDE, value );
}
}
public float Latitude
{
get
{
return this.GetAttribute<float>( LATITUDE );
}
set
{
this.SetAttribute( LATITUDE, value );
}
}
public Coordinate()
{
this.EnsureAttribute<float>(LONGITUDE);
this.EnsureAttribute<float>(LATITUDE);
}
}
那是坐标,那Places
呢?如何添加新地点?该文章似乎缺少此信息
经过多次尝试,我终于拼凑起来了。文章的关键(虽然没有很好解释)部分是:
Register the attributes, collections, and dictionaries with the base
class in the constructor using the following helper methods:
this.EnsureAttribute<TValue>( string name );
this.EnsureElement<TElement>( string name );
this.EnsureDictionary<TElement>( string name );
this.EnsureCollection<TElement>( string name );
所以 collection 与属性 "Ensured" 不同。所以 Places
class 的实现(从示例中)看起来像:
[Serializable]
public Places : Facet, IPlaces
{
private const string FIELD_PLACES = "Places";
public Places()
{
this.EnsureDictionary<IPlace>(FIELD_PLACES);
}
public IElementDictionary<IPlace> Places
{
get
{
return this.GetCollection<IPlace>(FIELD_PLACES);
}
}
}
注意不同的 Get(this.GetCollection<IPlace>(FIELD_PLACES);
) 和 Ensure 调用(this.EnsureDictionary<IPlace>(FIELD_PLACES);
)。如果您不这样做,您的 collection 将是 null
。 IPlace.Coordinate
将以相同的方式设置。通过调用它们,它将为您实例化正确的 collections。
添加也不简单(或解释)。 IElementDictionary
不公开 Add 方法。它确实暴露了 Create()
。使用反射工具快速查看它,您可以看到它创建了一个项目并将其添加到词典中:
public TElement Create(string key)
{
Assert.ArgumentNotNull(key, "key");
TElement tElement = ModelFactory.CreateElement<TElement>();
this.dictionary.Add(key, tElement);
return tElement;
}
所以添加到 Places 字典的方式如下:
IPlaces places = _contact.GetFacet<IPlaces>("name form XML config");
IPlace newPlace = places.Places.Create();
newPlace.Description = "test";
ICoordinate newCoord = newPlace.Coordinate.Create();
newCoord.Longitude = 0;
无需保存等,持久化等内部处理。
您需要注册所有 3 个 "elements",但只有最上面的 (IPlaces
) 需要进入 [=48= 的 <entities>
collection ].所以整个配置看起来像:
<sitecore>
<model>
<elements>
<element interface="Namespace.IPlaces, Dllname" implementation="Namespace.Places, Dllname" />
<element interface="Namespace.IPlace , Dllname" implementation="Namespace.Place, Dllname" />
<element interface="Namespace.ICoordinate, Dllname" implementation="Namespace.Coordinate , Dllname" />
</elements>
<entities>
<contact>
<facets>
<facet name="name form XML config" contract="Namespace.IPlaces, Dllname" />
</facets>
</contact>
</entities>
</model>
</sitecore>
Subsequently I've seen this article 其中涵盖了这一点并深入介绍了有关自定义数据的其他详细信息
This article 似乎暗示这是可能的,但似乎跳过了集合本身的关键实现。它列出了粗略的结构:
public interface ICoordinate : IElement
{
float Longitude { get; set; }
float Latitude { get; set; }
}
public interface IPlace : IElement
{
string Description { get; set; }
ICoordinate Coordinate { get; }
}
public interface IPlaces : IFacet
{
IElementDictionary<IPlace> Places { get; }
}
正是我需要的对象集合。那么我该如何实现呢?
[Serializable]
internal class Coordinate : Element, ICoordinate
{
private const string LONGITUDE = "Longitude";
private const string LATITUDE = "Latitude";
public float Longitude
{
get
{
return this.GetAttribute<float>( LONGITUDE );
}
set
{
this.SetAttribute( LONGITUDE, value );
}
}
public float Latitude
{
get
{
return this.GetAttribute<float>( LATITUDE );
}
set
{
this.SetAttribute( LATITUDE, value );
}
}
public Coordinate()
{
this.EnsureAttribute<float>(LONGITUDE);
this.EnsureAttribute<float>(LATITUDE);
}
}
那是坐标,那Places
呢?如何添加新地点?该文章似乎缺少此信息
经过多次尝试,我终于拼凑起来了。文章的关键(虽然没有很好解释)部分是:
Register the attributes, collections, and dictionaries with the base class in the constructor using the following helper methods:
this.EnsureAttribute<TValue>( string name ); this.EnsureElement<TElement>( string name ); this.EnsureDictionary<TElement>( string name ); this.EnsureCollection<TElement>( string name );
所以 collection 与属性 "Ensured" 不同。所以 Places
class 的实现(从示例中)看起来像:
[Serializable]
public Places : Facet, IPlaces
{
private const string FIELD_PLACES = "Places";
public Places()
{
this.EnsureDictionary<IPlace>(FIELD_PLACES);
}
public IElementDictionary<IPlace> Places
{
get
{
return this.GetCollection<IPlace>(FIELD_PLACES);
}
}
}
注意不同的 Get(this.GetCollection<IPlace>(FIELD_PLACES);
) 和 Ensure 调用(this.EnsureDictionary<IPlace>(FIELD_PLACES);
)。如果您不这样做,您的 collection 将是 null
。 IPlace.Coordinate
将以相同的方式设置。通过调用它们,它将为您实例化正确的 collections。
添加也不简单(或解释)。 IElementDictionary
不公开 Add 方法。它确实暴露了 Create()
。使用反射工具快速查看它,您可以看到它创建了一个项目并将其添加到词典中:
public TElement Create(string key)
{
Assert.ArgumentNotNull(key, "key");
TElement tElement = ModelFactory.CreateElement<TElement>();
this.dictionary.Add(key, tElement);
return tElement;
}
所以添加到 Places 字典的方式如下:
IPlaces places = _contact.GetFacet<IPlaces>("name form XML config");
IPlace newPlace = places.Places.Create();
newPlace.Description = "test";
ICoordinate newCoord = newPlace.Coordinate.Create();
newCoord.Longitude = 0;
无需保存等,持久化等内部处理。
您需要注册所有 3 个 "elements",但只有最上面的 (IPlaces
) 需要进入 [=48= 的 <entities>
collection ].所以整个配置看起来像:
<sitecore>
<model>
<elements>
<element interface="Namespace.IPlaces, Dllname" implementation="Namespace.Places, Dllname" />
<element interface="Namespace.IPlace , Dllname" implementation="Namespace.Place, Dllname" />
<element interface="Namespace.ICoordinate, Dllname" implementation="Namespace.Coordinate , Dllname" />
</elements>
<entities>
<contact>
<facets>
<facet name="name form XML config" contract="Namespace.IPlaces, Dllname" />
</facets>
</contact>
</entities>
</model>
</sitecore>
Subsequently I've seen this article 其中涵盖了这一点并深入介绍了有关自定义数据的其他详细信息