玻璃映射器将为放置在 GlassModels 上的 SitecoreQuery 和 SitecoreChildren 属性返回空对象或(无项目)。这些属性不采用任何此类参数,如果它们在上下文语言中不存在,我可以在其中指定它们以返回项目。例如,这些项目存在于 EN 中,但不存在于 en-ES 中。我需要在我的视图中进行大量空检查以避免空异常并使视图或控制器非常混乱。必须编写大量样板代码才能使其工作。在页面编辑器中,SitecoreChildren 返回项目,内容作者可以通过编辑项目上的任何字段以该语言版本创建项目。这会自动以该语言创建项目。但是,相同的代码在预览模式下会失败,因为 SitecoreChidren 将返回 null 并且您会看到空指针异常。SitecoreQuery 不会在页面编辑器中返回任何项目,然后内容作者将无法在页面编辑器中创建项目。如果我们可以将参数传递给 SiteocreQuery 属性,以便它禁用 VsersionCount 并返回不存在于该语言中的项目,那么为了使体验更好。
sitecore - 如何在 Sitecore 中为 SitecoreQuery 和 SitecoreChildren 属性启用 Glass Mapper 的 VersionCountDisabler
问问题
868 次
1 回答
2
这实际上是不可能的。GitHub b 上有一个问题,它可以很容易地创建一个自定义属性来处理这个非常容易。目前您需要创建一个新的类型映射器并从SitecoreQueryMapper
. 我在这里写了一篇关于如何创建自定义类型映射器的博客文章。您需要创建以下类(示例SitecoreQuery
)。
新配置:
public class SitecoreSharedQueryConfiguration : SitecoreQueryConfiguration
{
}
新属性:
public class SitecoreSharedQueryAttribute : SitecoreQueryAttribute
{
public SitecoreSharedQueryAttribute(string query) : base(query)
{
}
public override AbstractPropertyConfiguration Configure(PropertyInfo propertyInfo)
{
var config = new SitecoreSharedQueryConfiguration();
this.Configure(propertyInfo, config);
return config;
}
}
新类型映射器:
public class SitecoreSharedQueryTypeMapper : SitecoreQueryMapper
{
public SitecoreSharedQueryTypeMapper(IEnumerable<ISitecoreQueryParameter> parameters)
: base(parameters)
{
}
public override object MapToProperty(AbstractDataMappingContext mappingContext)
{
var scConfig = Configuration as SitecoreQueryConfiguration;
var scContext = mappingContext as SitecoreDataMappingContext;
using (new VersionCountDisabler())
{
if (scConfig != null && scContext != null)
{
string query = this.ParseQuery(scConfig.Query, scContext.Item);
if (scConfig.PropertyInfo.PropertyType.IsGenericType)
{
Type outerType = Glass.Mapper.Sc.Utilities.GetGenericOuter(scConfig.PropertyInfo.PropertyType);
if (typeof(IEnumerable<>) == outerType)
{
Type genericType = Utilities.GetGenericArgument(scConfig.PropertyInfo.PropertyType);
Func<IEnumerable<Item>> getItems;
if (scConfig.IsRelative)
{
getItems = () =>
{
try
{
return scContext.Item.Axes.SelectItems(query);
}
catch (Exception ex)
{
throw new MapperException("Failed to perform query {0}".Formatted(query), ex);
}
};
}
else
{
getItems = () =>
{
if (scConfig.UseQueryContext)
{
var conQuery = new Query(query);
var queryContext = new QueryContext(scContext.Item.Database.DataManager);
object obj = conQuery.Execute(queryContext);
var contextArray = obj as QueryContext[];
var context = obj as QueryContext;
if (contextArray == null)
contextArray = new[] { context };
return contextArray.Select(x => scContext.Item.Database.GetItem(x.ID));
}
return scContext.Item.Database.SelectItems(query);
};
}
return Glass.Mapper.Sc.Utilities.CreateGenericType(typeof(ItemEnumerable<>), new[] { genericType }, getItems, scConfig.IsLazy, scConfig.InferType, scContext.Service);
}
throw new NotSupportedException("Generic type not supported {0}. Must be IEnumerable<>.".Formatted(outerType.FullName));
}
{
Item result;
if (scConfig.IsRelative)
{
result = scContext.Item.Axes.SelectSingleItem(query);
}
else
{
result = scContext.Item.Database.SelectSingleItem(query);
}
return scContext.Service.CreateType(scConfig.PropertyInfo.PropertyType, result, scConfig.IsLazy, scConfig.InferType, null);
}
}
}
return null;
}
public override bool CanHandle(AbstractPropertyConfiguration configuration, Context context)
{
return configuration is SitecoreSharedQueryConfiguration;
}
}
并在您的 glass config 中配置新类型映射器(构造函数的映射器和参数):
container.Register(Component.For<AbstractDataMapper>().ImplementedBy<SitecoreSharedQueryTypeMapper>().LifeStyle.Transient);
container.Register(Component.For<IEnumerable<ISitecoreQueryParameter>>().ImplementedBy<List<ItemPathParameter>>().LifeStyle.Transient);
container.Register(Component.For<IEnumerable<ISitecoreQueryParameter>>().ImplementedBy<List<ItemIdParameter>>().LifeStyle.Transient);
container.Register(Component.For<IEnumerable<ISitecoreQueryParameter>>().ImplementedBy<List<ItemIdNoBracketsParameter>>().LifeStyle.Transient);
container.Register(Component.For<IEnumerable<ISitecoreQueryParameter>>().ImplementedBy<List<ItemEscapedPathParameter>>().LifeStyle.Transient);
container.Register(Component.For<IEnumerable<ISitecoreQueryParameter>>().ImplementedBy<List<ItemDateNowParameter>>().LifeStyle.Transient);
然后,您可以简单地将SitecoreQuery
模型上的属性更改为SitecoreSharedQuery
:
[SitecoreSharedQuery("./*")]
public virtual IEnumerable<YourModel> YourItems { get; set; }
对于孩子,您可以使用共享查询映射器并查询孩子,或者为新SitecoreSharedChildren
查询创建相同的类。
编辑:添加了绑定,IEnumerable<ISitecoreQueryParameter>
因为它们丢失了,因此引发了错误。
于 2014-10-29T20:14:03.707 回答