在运行时检查玻璃映射器 V3 类型
本文关键字:V3 类型 映射 玻璃 运行时 检查 | 更新日期: 2023-09-27 18:36:38
使用 Glass Mapper V3,是否可以检查 Sitecore 项目是否支持特定的 Glass Mapper 类/接口?
给定这些类
[SitecoreType]
public partial interface IPage : IGlassBase
{
// ... some properties here ...
}
[SitecoreType]
public partial interface IRateableItem : IGlassBase
{
// ... some properties here ...
}
我想做这样的事情
var context = SitecoreContext();
var item = context.GetCurrentItem<IRateableItem>();
if (item != null)
// it's an item that is composed of the Rateable Item template
不幸的是,如果我这样做,我确实会返回一个 IRateableItem 类型的项目,无论当前项目是否由该模板组成。
Dan
另一种解决方案是创建一个在 ObjectConstruction 管道中运行的自定义任务。
像这样:
public class LimitByTemplateTask : IObjectConstructionTask
{
private static readonly Type _templateCheck = typeof (ITemplateCheck);
public void Execute(ObjectConstructionArgs args)
{
if (args.Result != null)
return;
if ( _templateCheck.IsAssignableFrom(args.AbstractTypeCreationContext.RequestedType))
{
var scContext = args.AbstractTypeCreationContext as SitecoreTypeCreationContext;
var config = args.Configuration as SitecoreTypeConfiguration;
var template = scContext.SitecoreService.Database.GetTemplate(scContext.Item.TemplateID);
//check to see if any base template matched the template for the requested type
if (template.BaseTemplates.All(x => x.ID != config.TemplateId) && scContext.Item.TemplateID != config.TemplateId)
{
args.AbortPipeline();
}
}
}
}
public interface ITemplateCheck{}
然后,您将更改 IRateableItem 接口,使其具有它需要匹配并从 ITemplateCheck 继承的模板 ID:
[SitecoreType(TemplateId = "CF9B175D-872E-439A-B358-37A01155EEB1")]
public interface IRateableItem: ITemplateCheck, IGlassBase{}
最后,您需要在 GlassMapperScCustom 中使用 Castle IOC 容器注册新任务:
public static void CastleConfig(IWindsorContainer container){
var config = new Config();
container.Register(
Component.For<IObjectConstructionTask>().ImplementedBy<LimitByTemplateTask>(),
);
container.Install(new SitecoreInstaller(config));
}
我没有机会对此进行测试,所以如果有任何问题,请告诉我。
我使用此代码来确定项目是否可以作为某种类型的玻璃模型加载。我以您的IRateableItem类型为例:
public void Main()
{
var item = Sitecore.Context.Item;
if (item.TemplateID.Equals(GetSitecoreTypeTemplateId<IRateableItem>()))
{
// item is of the IRateableItem type
}
}
private ID GetSitecoreTypeTemplateId<T>() where T : class
{
// Get the GlassMapper context
var context = GetGlassContext();
// Retrieve the SitecoreTypeConfiguration for type T
var sitecoreClass = context[typeof(T)] as SitecoreTypeConfiguration;
return sitecoreClass.TemplateId;
}
private SitecoreService GetSitecoreService()
{
return new SitecoreService(global::Sitecore.Context.Database);
}
private Glass.Mapper.Context GetGlassContext()
{
return GetSitecoreService().GlassContext;
}
编辑:
添加此扩展方法,以便可以确定模板是否继承自某个基本模板。
public static bool InheritsFrom(this TemplateItem templateItem, ID templateId)
{
if (templateItem.ID == templateId)
{
return true;
}
foreach (var template in templateItem.BaseTemplates)
{
if (template.ID == templateId)
{
return true;
}
if (template.InheritsFrom(templateId))
{
return true;
}
}
return false;
}
所以现在你可以这样做:
if (item.Template.InheritsFrom(GetSitecoreTypeTemplateId<IRateableItem>()))
{
// item is of type IRateableItem
}
我还没有找到空检查的解决方案。但你能做的是:
首先将模板 ID 添加到两个模型的 SitecoreType 属性中:
[SitecoreType(TemplateId = "{your-template-id}")]
然后在代码中使用带有 InferType=true 参数的 GetCurrentItem<>() 方法:
var context = SitecoreContext();
var item = context.GetCurrentItem<IGlassBase>(InferType: true);
if (item is IRateableItem)
{
var rateableItem = item as IRateableItem;
// do more...
}
通过添加 TemplateID 并使用 InferType:true 参数,Glass 将尝试根据 TemplateID 将项目映射到更好的对象,然后 IGlassBase。
如果有更好的解决方案来解决这个问题,我也有兴趣。