Glass.Mapper 和使用界面创建 Sitecore 项目
本文关键字:创建 Sitecore 项目 界面 Mapper Glass | 更新日期: 2023-09-27 18:32:27
这是来自Twitter的问题:
从接口模型创建项的模式是什么?使用 sitecoreService.Create<T,K>(T newItem, K parent)
其中 T
是一个接口,需要添加一个类来创建新项。有没有办法直接从界面创建它们?
这是一个挑战,因为您需要一个具体版本的接口来在保存值之前写入它们。简单的解决方案是使用像NSubstitute这样的模拟框架,使用以下接口:
[SitecoreType(TemplateId = "{7FC4F278-ADDA-4683-944C-554D0913CB33}", AutoMap = true)]
public interface StubInterfaceAutoMapped
{
Guid Id { get; set; }
Language Language { get; set; }
string Path { get; set; }
int Version { get; set; }
string Name { get; set; }
string StringField { get; set; }
}
我可以创建以下测试:
[Test]
public void Create_UsingInterface_CreatesANewItem()
{
//Assign
string parentPath = "/sitecore/content/Tests/SitecoreService/Create";
string childPath = "/sitecore/content/Tests/SitecoreService/Create/newChild";
string fieldValue = Guid.NewGuid().ToString();
var db = Sitecore.Configuration.Factory.GetDatabase("master");
var context = Context.Create(Utilities.CreateStandardResolver());
context.Load(new SitecoreAttributeConfigurationLoader("Glass.Mapper.Sc.Integration"));
var service = new SitecoreService(db);
using (new SecurityDisabler())
{
var parentItem = db.GetItem(parentPath);
parentItem.DeleteChildren();
}
var parent = service.GetItem<StubClass>(parentPath);
var child = Substitute.For<StubInterfaceAutoMapped>();
child.Name = "newChild";
child.StringField = fieldValue;
//Act
using (new SecurityDisabler())
{
service.Create(parent, child);
}
//Assert
var newItem = db.GetItem(childPath);
Assert.AreEqual(fieldValue, newItem["StringField"]);
using (new SecurityDisabler())
{
newItem.Delete();
}
Assert.AreEqual(child.Name, newItem.Name);
Assert.AreEqual(child.Id, newItem.ID.Guid);
}
这是因为 Glass.Mapper 解析要映射的类型的方式:
/// <summary>
/// Gets the type configuration.
/// </summary>
/// <param name="obj">The obj.</param>
/// <returns>AbstractTypeConfiguration.</returns>
public AbstractTypeConfiguration GetTypeConfiguration(object obj)
{
var type = obj.GetType();
var config = TypeConfigurations.ContainsKey(type) ? TypeConfigurations[type] : null;
if (config != null) return config;
//check base type encase of proxy
config = TypeConfigurations.ContainsKey(type.BaseType) ? TypeConfigurations[type.BaseType] : null;
if (config != null) return config;
//check interfaces encase this is an interface proxy
string name = type.Name;
//ME - I added the OrderByDescending in response to issue 53
// raised on the Glass.Sitecore.Mapper project. Longest name should be compared first
// to get the most specific interface
var interfaceType = type.GetInterfaces().OrderByDescending(x=>x.Name.Length).FirstOrDefault(x => name.Contains(x.Name));
if (interfaceType != null)
config = TypeConfigurations.ContainsKey(interfaceType) ? TypeConfigurations[interfaceType] : null;
return config;
}
请注意,如果找不到直接类型匹配项,它将开始根据与传入类型关联的接口确定类型,并使用基于名称找到的第一个接口。现在我怀疑 NSubstitute 有效,因为它也使用 Castle 动态代理,用其他模拟框架测试它会很有趣。