How to lazy loading a property using a custom attribute

I want to create a custom attribute using Glass Mapper to get the Sitecore url because it is not possible to lazy load the property from SitecoreInfo(SitecoreInfoType.Url)

and we have some performance issues loading mapped element urls where the url will never be.

This is what I got so far:

Configuration

public class SitecoreUrlConfiguration : AbstractPropertyConfiguration
{
    public SitecoreInfoUrlOptions UrlOptions { get; set; }

    public bool IsLazy { get; set; }
}

      

Attribute

public class SitecoreUrlAttribute : AbstractPropertyAttribute
{
    public SitecoreUrlAttribute()
    {
        this.IsLazy = true;
        this.UrlOptions = SitecoreInfoUrlOptions.Default;
    }

    /// <summary>
    /// Gets or sets a value indicating whether is lazy.
    /// </summary>
    public bool IsLazy { get; set; }

    public SitecoreInfoUrlOptions UrlOptions { get; set; }

    public override AbstractPropertyConfiguration Configure(PropertyInfo propertyInfo)
    {
        var config = new SitecoreUrlConfiguration();
        this.Configure(propertyInfo, config);
        return config;
    }

    public void Configure(PropertyInfo propertyInfo, SitecoreUrlConfiguration config)
    {
        config.UrlOptions = this.UrlOptions;
        config.IsLazy = this.IsLazy;

        base.Configure(propertyInfo, config);
    }
}

      

Mapper

public class SitecoreUrlMapper : AbstractDataMapper
{
    public override object MapToProperty(AbstractDataMappingContext mappingContext)
    {
        var context = mappingContext as SitecoreDataMappingContext;
        if (context == null)
        {
            throw new MapperException("Mapping Context is null");
        }

        var item = context.Item;
        var scConfig = this.Configuration as SitecoreUrlConfiguration;

        if (scConfig == null)
        {
            throw new MapperException("SitecoreUrlConfiguration is null");
        }

        var urlOptions = Utilities.CreateUrlOptions(scConfig.UrlOptions);

        urlOptions.Language = null;
        // now, what?
    }
}

      

So far so good. But how can I be lazy to load the url in cartographer? Anyone have an idea?

+3


source to share


2 answers


The only way I can actually see is to map Lazy<T>

and add a new property to the class that returns the value of that when it is accessed. So, in your cartographer where you put // now what?

, I would return the lazy string:

return new Lazy<string>(() => LinkManager.GetItemUrl(item, urlOptions));

      



Then, in your model, put these two properties:

[SitecoreUrl]
public Lazy<string> LazyUrl { private get; set; }

[SitecoreIgnore]
public virtual string Url
{
    get
    {
        return this.LazyUrl.Value;
    }
}

      

+4


source


You can achieve pretty similar to this with a little creativity and new delegate functionality

On a smooth configuration map, this type:



SitecoreType<IWhatever> sitecoreType = new SitecoreType<IWhatever>();
sitecoreType.Delegate(y => y.Url).GetValue(GetLazyUrl);

private LazyString GetLazyUrl(SitecoreDataMappingContext arg)
{
    var item = context.Item;

    return new LazyString(
        () => 
        {
           // the necessary actions to get the url
        });
}

public class LazyString : Lazy<string>
{
    public LazyString(Func<string> valueFactory) : base(valueFactory)
    {
    }

    public override string ToString()
    {
        return Value;
    }

    public static implicit operator string(LazyString lazyString)
    {
        return lazyString.Value;
    }
}

      

It is not a string, but for the purposes of many applications, it will behave like one.

0


source







All Articles