0
這是一個question from Twitter:Glass.Mapper和創建Sitecore的項目使用接口
什麼是創建從接口的型號項目的模式?使用sitecoreService.Create<T,K>(T newItem, K parent)
其中T
是一個接口,需要添加一個類來創建新項目。有沒有一種方法可以直接從界面創建它們?
這是一個question from Twitter:Glass.Mapper和創建Sitecore的項目使用接口
什麼是創建從接口的型號項目的模式?使用sitecoreService.Create<T,K>(T newItem, K parent)
其中T
是一個接口,需要添加一個類來創建新項目。有沒有一種方法可以直接從界面創建它們?
這是一個挑戰,因爲您需要接口的具體版本才能在保存之前寫入值。簡單的解決方法是使用像NSubstitute嘲弄的框架,uisng如下界面:
[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 Dynamic Proxies,用其他模擬框架測試它會很有趣。
感謝您的快速響應並解釋了這是如何工作的,特別是對接口名稱長度的依賴。我不確定我喜歡在我的主線代碼中包含隔離框架,所以我可能會在創建該項目的類中或附近創建接口的實現。這感覺有點多餘,但從技術上講仍然是DRY,因爲接口是記錄的定義。 –