0

グラス マッパーは、GlassModels に配置された SitecoreQuery および SitecoreChildren 属性に対して null オブジェクトまたは (アイテムなし) を返します。これらの属性は、コンテキスト言語に存在しない場合にアイテムを返すように指定できるようなパラメーターを取りません。たとえば、アイテムは EN に存在しますが、en-ES には存在しません。Null 例外を回避するために、ビューに多くの null チェックを配置する必要があり、ビューまたはコントローラーが非常に面倒になります。それを機能させるために書かなければならないのは、多くのボイラープレートコードです。ページ エディターでは、SitecoreChildren がアイテムを返し、コンテンツ作成者はアイテムの任意のフィールドを編集して、その言語バージョンでアイテムを作成できます。これにより、その言語で項目が自動的に作成されます。ただし、SitecoreChidren が null を返し、null ポインター例外が表示されるため、プレビュー モードでは同じコードが失敗します。SitecoreQuery はページ エディターでアイテムを返さないため、コンテンツ作成者はページ エディターでアイテムを作成できません。パラメータを SiteocreQuery 属性に渡して、VsersionCount を無効にし、その言語に存在しない場合はアイテムを返すことができれば、エクスペリエンスを向上させることができます。

4

1 に答える 1

2

これは実際には不可能です。これを非常に簡単に処理するためのカスタム属性を簡単に作成できるGitHu 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;
    }
}

そして、グラス構成で新しい型マッパーを構成します (コンストラクターのマッパーとパラメーター):

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 に答える