Reputation: 983
Using Glass Mapper V3, is it possible to check whether a Sitecore item supports a specific Glass Mapper class/interface?
Given these classes
[SitecoreType]
public partial interface IPage : IGlassBase
{
// ... some properties here ...
}
[SitecoreType]
public partial interface IRateableItem : IGlassBase
{
// ... some properties here ...
}
I would like to do something like this
var context = SitecoreContext();
var item = context.GetCurrentItem<IRateableItem>();
if (item != null)
// it's an item that is composed of the Rateable Item template
Unfortunately, if I do that, I do get an item of the type IRateableItem returned, regardless of whether the current item is composed of that template or not.
Upvotes: 4
Views: 1645
Reputation: 4092
I haven't found a solution to the null-check as well. But what you can do is this:
First add the TemplateId to the SitecoreType attribute for both your models:
[SitecoreType(TemplateId = "{your-template-id}")]
Then in your code use the GetCurrentItem<>() method with the InferType=true parameter:
var context = SitecoreContext();
var item = context.GetCurrentItem<IGlassBase>(InferType: true);
if (item is IRateableItem)
{
var rateableItem = item as IRateableItem;
// do more...
}
By adding the TemplateID and using the InferType:true parameter, Glass will try to map the item to a better object then IGlassBase, based on the TemplateID.
If there is a nicer solution to solve this, I'm interested as well.
Upvotes: 2
Reputation: 6528
Dan
Another solution would be to create a custom task that runs in the ObjectConstruction pipeline.
Something like this:
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{}
You would then change you IRateableItem inteface to have the template ID it needs to match and inherit from ITemplateCheck:
[SitecoreType(TemplateId = "CF9B175D-872E-439A-B358-37A01155EEB1")]
public interface IRateableItem: ITemplateCheck, IGlassBase{}
Finally you will need to register the new task with the Castle IOC container in GlassMapperScCustom:
public static void CastleConfig(IWindsorContainer container){
var config = new Config();
container.Register(
Component.For<IObjectConstructionTask>().ImplementedBy<LimitByTemplateTask>(),
);
container.Install(new SitecoreInstaller(config));
}
I haven't had a chance to test this so let me know if there are any problems.
Upvotes: 4
Reputation: 8877
I used this code to determine if an Item could be loaded as a Glass model of a certain type. I've used your IRateableItem type as an example:
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;
}
EDIT:
Add this extension method so that you can determine whether a Template inherits from a certain base template.
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;
}
So now you can do this:
if (item.Template.InheritsFrom(GetSitecoreTypeTemplateId<IRateableItem>()))
{
// item is of type IRateableItem
}
Upvotes: 2