Implementing dynamic query operators

--HG--
branch : 1.x
This commit is contained in:
Sebastien Ros
2011-10-11 15:12:50 -07:00
parent ec4cb77f78
commit 190bac9ba8
7 changed files with 527 additions and 9 deletions

View File

@@ -0,0 +1,233 @@
using System.Linq;
using Autofac;
using Moq;
using NHibernate;
using NUnit.Framework;
using Orchard.ContentManagement.MetaData;
using Orchard.Data;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Handlers;
using Orchard.ContentManagement.Records;
using Orchard.DisplayManagement;
using Orchard.DisplayManagement.Descriptors;
using Orchard.Environment.Extensions;
using Orchard.Tests.ContentManagement.Handlers;
using Orchard.Tests.ContentManagement.Records;
using Orchard.Tests.ContentManagement.Models;
using Orchard.DisplayManagement.Implementation;
using Orchard.Tests.Stubs;
namespace Orchard.Tests.ContentManagement {
[TestFixture]
public class DynamicContentQueryTests {
private IContainer _container;
private IContentManager _manager;
private ISessionFactory _sessionFactory;
private ISession _session;
[TestFixtureSetUp]
public void InitFixture() {
var databaseFileName = System.IO.Path.GetTempFileName();
_sessionFactory = DataUtility.CreateSessionFactory(
databaseFileName,
typeof(GammaRecord),
typeof(DeltaRecord),
typeof(EpsilonRecord),
typeof(ContentItemVersionRecord),
typeof(ContentItemRecord),
typeof(ContentTypeRecord));
}
[SetUp]
public void Init() {
var builder = new ContainerBuilder();
builder.RegisterModule(new ContentModule());
builder.RegisterType<DefaultContentManager>().As<IContentManager>().SingleInstance();
builder.RegisterType<DefaultContentManagerSession>().As<IContentManagerSession>();
builder.RegisterInstance(new Mock<IContentDefinitionManager>().Object);
builder.RegisterInstance(new Mock<IContentDisplay>().Object);
builder.RegisterType<AlphaPartHandler>().As<IContentHandler>();
builder.RegisterType<BetaPartHandler>().As<IContentHandler>();
builder.RegisterType<GammaPartHandler>().As<IContentHandler>();
builder.RegisterType<DeltaPartHandler>().As<IContentHandler>();
builder.RegisterType<EpsilonPartHandler>().As<IContentHandler>();
builder.RegisterType<FlavoredPartHandler>().As<IContentHandler>();
builder.RegisterType<StyledHandler>().As<IContentHandler>();
builder.RegisterType<DefaultShapeTableManager>().As<IShapeTableManager>();
builder.RegisterType<ShapeTableLocator>().As<IShapeTableLocator>();
builder.RegisterType<DefaultShapeFactory>().As<IShapeFactory>();
builder.RegisterGeneric(typeof(Repository<>)).As(typeof(IRepository<>));
builder.RegisterType<StubExtensionManager>().As<IExtensionManager>();
builder.RegisterType<DefaultContentDisplay>().As<IContentDisplay>();
_session = _sessionFactory.OpenSession();
builder.RegisterInstance(new DefaultContentManagerTests.TestSessionLocator(_session)).As<ISessionLocator>();
_session.Delete(string.Format("from {0}", typeof(GammaRecord).FullName));
_session.Delete(string.Format("from {0}", typeof(DeltaRecord).FullName));
_session.Delete(string.Format("from {0}", typeof(EpsilonRecord).FullName));
_session.Delete(string.Format("from {0}", typeof(ContentItemVersionRecord).FullName));
_session.Delete(string.Format("from {0}", typeof(ContentItemRecord).FullName));
_session.Delete(string.Format("from {0}", typeof(ContentTypeRecord).FullName));
_session.Flush();
_session.Clear();
_container = builder.Build();
_manager = _container.Resolve<IContentManager>();
}
private void AddSampleData() {
_manager.Create<AlphaPart>("alpha", init => { });
_manager.Create<BetaPart>("beta", init => { });
_manager.Create<GammaPart>("gamma", init => { init.Record.Frap = "the frap value"; });
_manager.Create<DeltaPart>("delta", init => { init.Record.Quux = "the quux value"; });
_session.Flush();
}
[Test]
public void SpecificTypeIsReturnedWhenSpecified() {
AddSampleData();
var alphaBeta = _manager.Query().Where(x => x.WithRecord("ContentType").In("Name", new [] {"alpha", "beta"})).List();
Assert.That(alphaBeta.Count(), Is.EqualTo(2));
Assert.That(alphaBeta.Count(x => x.Has<AlphaPart>()), Is.EqualTo(1));
Assert.That(alphaBeta.Count(x => x.Has<BetaPart>()), Is.EqualTo(1));
Assert.That(alphaBeta.Count(x => x.Has<GammaPart>()), Is.EqualTo(0));
Assert.That(alphaBeta.Count(x => x.Has<DeltaPart>()), Is.EqualTo(0));
var gammaDelta = _manager.Query().Where(x => x.WithRecord("ContentType").In("Name", new[] { "gamma", "delta" })).List();
Assert.That(gammaDelta.Count(), Is.EqualTo(2));
Assert.That(gammaDelta.Count(x => x.Has<AlphaPart>()), Is.EqualTo(0));
Assert.That(gammaDelta.Count(x => x.Has<BetaPart>()), Is.EqualTo(0));
Assert.That(gammaDelta.Count(x => x.Has<GammaPart>()), Is.EqualTo(1));
Assert.That(gammaDelta.Count(x => x.Has<DeltaPart>()), Is.EqualTo(1));
}
[Test]
public void WherePredicateRestrictsResults() {
AddSampleData();
_manager.Create<GammaPart>("gamma", init => { init.Record.Frap = "one"; });
_manager.Create<GammaPart>("gamma", init => { init.Record.Frap = "two"; });
_manager.Create<GammaPart>("gamma", init => { init.Record.Frap = "three"; });
_manager.Create<GammaPart>("gamma", init => { init.Record.Frap = "four"; });
_session.Flush();
var twoOrFour = _manager.Query<GammaPart, GammaRecord>()
.Where(x => x.WithRecord("GammaRecord").Or(a => a.Eq("Frap", "one"), b => b.Eq("Frap", "four")))
.List();
Assert.That(twoOrFour.Count(), Is.EqualTo(2));
Assert.That(twoOrFour.Count(x => x.Has<GammaPart>()), Is.EqualTo(2));
Assert.That(twoOrFour.Count(x => x.Get<GammaPart>().Record.Frap == "one"), Is.EqualTo(1));
Assert.That(twoOrFour.Count(x => x.Get<GammaPart>().Record.Frap == "four"), Is.EqualTo(1));
}
[Test]
public void EmptyWherePredicateRequiresRecord() {
AddSampleData();
var gammas = _manager.Query().Where(x => x.WithRecord("GammaRecord")).List(); // simulates an inner join
var deltas = _manager.Query().Where(x => x.WithRecord("DeltaRecord")).List();
Assert.That(gammas.Count(), Is.EqualTo(1));
Assert.That(deltas.Count(), Is.EqualTo(1));
Assert.That(gammas.AsPart<GammaPart>().Single().Record.Frap, Is.EqualTo("the frap value"));
Assert.That(deltas.AsPart<DeltaPart>().Single().Record.Quux, Is.EqualTo("the quux value"));
}
[Test]
public void OrderMaySortOnJoinedRecord() {
AddSampleData();
_manager.Create<GammaPart>("gamma", init => { init.Record.Frap = "one"; });
_manager.Create<GammaPart>("gamma", init => { init.Record.Frap = "two"; });
_manager.Create<GammaPart>("gamma", init => { init.Record.Frap = "three"; });
_manager.Create<GammaPart>("gamma", init => { init.Record.Frap = "four"; });
_session.Flush();
_session.Clear();
var ascending = _manager.Query("gamma")
.OrderBy(x => x.WithRecord("GammaRecord").Asc("Frap"))
.List<GammaPart>().ToList();
Assert.That(ascending.Count(), Is.EqualTo(5));
Assert.That(ascending.First().Record.Frap, Is.EqualTo("four"));
Assert.That(ascending.Last().Record.Frap, Is.EqualTo("two"));
_session.Clear();
var descending = _manager.Query<GammaPart, GammaRecord>()
.OrderBy(x => x.WithRecord("GammaRecord").Desc("Frap"))
.List().ToList();
Assert.That(descending.Count(), Is.EqualTo(5));
Assert.That(descending.First().Record.Frap, Is.EqualTo("two"));
Assert.That(descending.Last().Record.Frap, Is.EqualTo("four"));
}
[Test]
public void SkipAndTakeProvidePagination() {
AddSampleData();
_manager.Create<GammaPart>("gamma", init => { init.Record.Frap = "one"; });
_manager.Create<GammaPart>("gamma", init => { init.Record.Frap = "two"; });
_manager.Create<GammaPart>("gamma", init => { init.Record.Frap = "three"; });
_manager.Create<GammaPart>("gamma", init => { init.Record.Frap = "four"; });
_session.Flush();
var reverseById = _manager.Query()
.OrderBy(x => x.WithRecord("GammaRecord").Desc("Id"))
.List();
var subset = _manager.Query()
.OrderBy(x => x.WithRecord("GammaRecord").Desc("Id"))
.Slice(2, 3);
Assert.That(subset.Count(), Is.EqualTo(3));
Assert.That(subset.First().Id, Is.EqualTo(reverseById.Skip(2).First().Id));
Assert.That(subset.Skip(1).First().Id, Is.EqualTo(reverseById.Skip(3).First().Id));
Assert.That(subset.Skip(2).First().Id, Is.EqualTo(reverseById.Skip(4).First().Id));
}
[Test]
public void QueryShouldJoinVersionedRecords() {
AddSampleData();
_manager.Create<GammaPart>("gamma", init => {
init.Record.Frap = "one";
init.As<EpsilonPart>().Record.Quad = "1";
});
_manager.Create<GammaPart>("gamma", init => {
init.Record.Frap = "two";
init.As<EpsilonPart>().Record.Quad = "2";
});
_manager.Create<GammaPart>("gamma", init => {
init.Record.Frap = "three";
init.As<EpsilonPart>().Record.Quad = "3";
});
_manager.Create<GammaPart>("gamma", init => {
init.Record.Frap = "four";
init.As<EpsilonPart>().Record.Quad = "4";
});
_session.Flush();
_session.Clear();
var results = _manager.Query("gamma")
.Where(x => x.WithVersionRecord("EpsilonRecord").Or(a => a.Eq("Quad", "2"), b => b.Eq("Quad", "3")))
.OrderBy(x => x.WithVersionRecord("EpsilonRecord").Desc("Quad"))
.List<EpsilonPart>();
Assert.That(results.Count(), Is.EqualTo(2));
Assert.That(results.First().Record, Has.Property("Quad").EqualTo("3"));
Assert.That(results.Last().Record, Has.Property("Quad").EqualTo("2"));
}
}
}

View File

@@ -169,6 +169,7 @@
<SubType>Code</SubType>
</Compile>
<Compile Include="ContentManagement\ContentQueryTests.cs" />
<Compile Include="ContentManagement\DynamicContentQueryTests.cs" />
<Compile Include="ContentManagement\DefaultContentManagerTests.cs">
<SubType>Code</SubType>
</Compile>

View File

@@ -1,4 +1,5 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
@@ -30,37 +31,36 @@ namespace Orchard.ContentManagement {
return _session;
}
ICriteria BindCriteriaByPath(ICriteria criteria, string path) {
internal ICriteria BindCriteriaByPath(ICriteria criteria, string path) {
return criteria.GetCriteriaByPath(path) ?? criteria.CreateCriteria(path);
}
ICriteria BindTypeCriteria() {
internal ICriteria BindTypeCriteria() {
// ([ContentItemVersionRecord] >join> [ContentItemRecord]) >join> [ContentType]
return BindCriteriaByPath(BindItemCriteria(), "ContentType");
}
ICriteria BindItemCriteria() {
internal ICriteria BindItemCriteria() {
// [ContentItemVersionRecord] >join> [ContentItemRecord]
return BindCriteriaByPath(BindItemVersionCriteria(), "ContentItemRecord");
}
ICriteria BindItemVersionCriteria() {
internal ICriteria BindItemVersionCriteria() {
if (_itemVersionCriteria == null) {
_itemVersionCriteria = BindSession().CreateCriteria<ContentItemVersionRecord>();
}
return _itemVersionCriteria;
}
ICriteria BindPartCriteria<TRecord>() where TRecord : ContentPartRecord {
internal ICriteria BindPartCriteria<TRecord>() where TRecord : ContentPartRecord {
if (typeof(TRecord).IsSubclassOf(typeof(ContentPartVersionRecord))) {
return BindCriteriaByPath(BindItemVersionCriteria(), typeof(TRecord).Name);
}
return BindCriteriaByPath(BindItemCriteria(), typeof(TRecord).Name);
}
private void ForType(params string[] contentTypeNames) {
if (contentTypeNames != null && contentTypeNames.Length != 0)
BindTypeCriteria().Add(Restrictions.InG("Name", contentTypeNames));
@@ -92,6 +92,15 @@ namespace Orchard.ContentManagement {
}
}
private void Where(Action<IExpressionFactory> expression) {
var expressionFactory = new DefaultExpressionFactory(this);
expression(expressionFactory);
if (expressionFactory.Criterion != null) {
expressionFactory.Criteria.Add(expressionFactory.Criterion);
}
}
private void OrderBy<TRecord, TKey>(Expression<Func<TRecord, TKey>> keySelector) where TRecord : ContentPartRecord {
// build a linq to nhibernate expression
var options = new QueryOptions();
@@ -108,6 +117,15 @@ namespace Orchard.ContentManagement {
}
}
private void OrderBy(Action<ISortFactory> expression) {
var sortFactory = new DefaultSortFactory(this);
expression(sortFactory);
if (sortFactory.Order != null) {
sortFactory.Criteria.AddOrder(sortFactory.Order);
}
}
private void OrderByDescending<TRecord, TKey>(Expression<Func<TRecord, TKey>> keySelector) where TRecord : ContentPartRecord {
// build a linq to nhibernate expression
var options = new QueryOptions();
@@ -126,7 +144,7 @@ namespace Orchard.ContentManagement {
private IEnumerable<ContentItem> Slice(int skip, int count) {
var criteria = BindItemVersionCriteria();
criteria.ApplyVersionOptionsRestrictions(_versionOptions);
// TODO: put 'removed false' filter in place
@@ -197,6 +215,11 @@ namespace Orchard.ContentManagement {
return new ContentQuery<T, TRecord>(_query);
}
IContentQuery<T> IContentQuery<T>.Where(Action<IExpressionFactory> predicate) {
_query.Where(predicate);
return new ContentQuery<T>(_query);
}
IContentQuery<T, TRecord> IContentQuery<T>.Where<TRecord>(Expression<Func<TRecord, bool>> predicate) {
_query.Where(predicate);
return new ContentQuery<T, TRecord>(_query);
@@ -211,8 +234,12 @@ namespace Orchard.ContentManagement {
_query.OrderByDescending(keySelector);
return new ContentQuery<T, TRecord>(_query);
}
}
IContentQuery<T> IContentQuery<T>.OrderBy(Action<ISortFactory> order) {
_query.OrderBy(order);
return new ContentQuery<T>(_query);
}
}
class ContentQuery<T, TR> : ContentQuery<T>, IContentQuery<T, TR>
where T : IContent
@@ -242,6 +269,200 @@ namespace Orchard.ContentManagement {
}
}
public class DefaultExpressionFactory : IExpressionFactory {
private readonly DefaultContentQuery _query;
public ICriterion Criterion { get; private set; }
public ICriteria Criteria { get; private set; }
public DefaultExpressionFactory(DefaultContentQuery query) {
_query = query;
}
public IExpressionFactory WithRecord(string path) {
Criteria = _query.BindCriteriaByPath(_query.BindItemCriteria(), path);
return this;
}
public IExpressionFactory WithVersionRecord(string path) {
Criteria = _query.BindCriteriaByPath(_query.BindItemVersionCriteria(), path);
return this;
}
public void Eq(string propertyName, object value) {
Criterion = Restrictions.Eq(propertyName, value);
}
public void Like(string propertyName, object value) {
Criterion = Restrictions.Like(propertyName, value);
}
public void Like(string propertyName, string value, MatchMode matchMode, char? escapeChar) {
Criterion = Restrictions.Like(propertyName, value);
}
public void Like(string propertyName, string value, MatchMode matchMode) {
Criterion = Restrictions.Like(propertyName, value);
}
public void InsensitiveLike(string propertyName, string value, MatchMode matchMode) {
Criterion = Restrictions.InsensitiveLike(propertyName, value);
}
public void InsensitiveLike(string propertyName, object value) {
Criterion = Restrictions.InsensitiveLike(propertyName, value);
}
public void Gt(string propertyName, object value) {
Criterion = Restrictions.Gt(propertyName, value);
}
public void Lt(string propertyName, object value) {
Criterion = Restrictions.Lt(propertyName, value);
}
public void Le(string propertyName, object value) {
Criterion = Restrictions.Le(propertyName, value);
}
public void Ge(string propertyName, object value) {
Criterion = Restrictions.Ge(propertyName, value);
}
public void Between(string propertyName, object lo, object hi) {
Criterion = Restrictions.Between(propertyName, lo, hi);
}
public void In(string propertyName, object[] values) {
Criterion = Restrictions.In(propertyName, values);
}
public void In(string propertyName, ICollection values) {
Criterion = Restrictions.In(propertyName, values);
}
public void InG<T>(string propertyName, ICollection<T> values) {
Criterion = Restrictions.InG(propertyName, values);
}
public void IsNull(string propertyName) {
Criterion = Restrictions.IsNull(propertyName);
}
public void EqProperty(string propertyName, string otherPropertyName) {
Criterion = Restrictions.EqProperty(propertyName, otherPropertyName);
}
public void NotEqProperty(string propertyName, string otherPropertyName) {
Criterion = Restrictions.NotEqProperty(propertyName, otherPropertyName);
}
public void GtProperty(string propertyName, string otherPropertyName) {
Criterion = Restrictions.GtProperty(propertyName, otherPropertyName);
}
public void GeProperty(string propertyName, string otherPropertyName) {
Criterion = Restrictions.GeProperty(propertyName, otherPropertyName);
}
public void LtProperty(string propertyName, string otherPropertyName) {
Criterion = Restrictions.LtProperty(propertyName, otherPropertyName);
}
public void LeProperty(string propertyName, string otherPropertyName) {
Criterion = Restrictions.LeProperty(propertyName, otherPropertyName);
}
public void IsNotNull(string propertyName) {
Criterion = Restrictions.IsNotNull(propertyName);
}
public void IsNotEmpty(string propertyName) {
Criterion = Restrictions.IsNotEmpty(propertyName);
}
public void IsEmpty(string propertyName) {
Criterion = Restrictions.IsEmpty(propertyName);
}
public void And(Action<IExpressionFactory> lhs, Action<IExpressionFactory> rhs) {
lhs(this);
ICriterion a = Criterion;
rhs(this);
ICriterion b = Criterion;
Criterion = Restrictions.And(a, b);
}
public void Or(Action<IExpressionFactory> lhs, Action<IExpressionFactory> rhs) {
lhs(this);
ICriterion a = Criterion;
rhs(this);
ICriterion b = Criterion;
Criterion = Restrictions.Or(a, b);
}
public void Not(Action<IExpressionFactory> expression) {
expression(this);
ICriterion a = Criterion;
Criterion = Restrictions.Not(a);
}
public void Conjunction(Action<IExpressionFactory> expression, params Action<IExpressionFactory>[] otherExpressions) {
var junction = Restrictions.Conjunction();
foreach (var exp in Enumerable.Empty<Action<IExpressionFactory>>().Union(new[] { expression }).Union(otherExpressions)) {
exp(this);
junction.Add(Criterion);
}
Criterion = junction;
}
public void Disjunction(Action<IExpressionFactory> expression, params Action<IExpressionFactory>[] otherExpressions) {
var junction = Restrictions.Disjunction();
foreach (var exp in Enumerable.Empty<Action<IExpressionFactory>>().Union(new[] { expression }).Union(otherExpressions)) {
exp(this);
junction.Add(Criterion);
}
Criterion = junction;
}
public void AllEq(IDictionary propertyNameValues) {
Criterion = Restrictions.AllEq(propertyNameValues);
}
public void NaturalId() {
Criterion = Restrictions.NaturalId();
}
}
public class DefaultSortFactory : ISortFactory {
private readonly DefaultContentQuery _query;
public Order Order { get; private set; }
public ICriteria Criteria { get; private set; }
public DefaultSortFactory(DefaultContentQuery query) {
_query = query;
}
public ISortFactory WithRecord(string path) {
Criteria = _query.BindCriteriaByPath(_query.BindItemCriteria(), path);
return this;
}
public ISortFactory WithVersionRecord(string path) {
Criteria = _query.BindCriteriaByPath(_query.BindItemVersionCriteria(), path);
return this;
}
public void Asc(string propertyName) {
Order = Order.Asc(propertyName);
}
public void Desc(string propertyName) {
Order = Order.Desc(propertyName);
}
}
}
internal static class CriteriaExtensions {

View File

@@ -5,7 +5,7 @@ using Orchard.ContentManagement.Records;
namespace Orchard.ContentManagement {
public interface IContentQuery {
public interface IContentQuery{
IContentManager ContentManager { get; }
IContentQuery<TPart> ForPart<TPart>() where TPart : IContent;
}
@@ -20,7 +20,10 @@ namespace Orchard.ContentManagement {
IContentQuery<TPart, TRecord> Join<TRecord>() where TRecord : ContentPartRecord;
IContentQuery<TPart> Where(Action<IExpressionFactory> predicate);
IContentQuery<TPart, TRecord> Where<TRecord>(Expression<Func<TRecord, bool>> predicate) where TRecord : ContentPartRecord;
IContentQuery<TPart> OrderBy(Action<ISortFactory> order);
IContentQuery<TPart, TRecord> OrderBy<TRecord, TKey>(Expression<Func<TRecord, TKey>> keySelector) where TRecord : ContentPartRecord;
IContentQuery<TPart, TRecord> OrderByDescending<TRecord, TKey>(Expression<Func<TRecord, TKey>> keySelector) where TRecord : ContentPartRecord;
}

View File

@@ -0,0 +1,49 @@
using System;
using System.Collections;
using System.Collections.Generic;
namespace Orchard.ContentManagement {
public interface IExpressionFactory {
IExpressionFactory WithRecord(string recordName);
IExpressionFactory WithVersionRecord(string recordName);
void Eq(string propertyName, object value);
void Like(string propertyName, object value);
void Like(string propertyName, string value, MatchMode matchMode, char? escapeChar);
void Like(string propertyName, string value, MatchMode matchMode);
void InsensitiveLike(string propertyName, string value, MatchMode matchMode);
void InsensitiveLike(string propertyName, object value);
void Gt(string propertyName, object value);
void Lt(string propertyName, object value);
void Le(string propertyName, object value);
void Ge(string propertyName, object value);
void Between(string propertyName, object lo, object hi);
void In(string propertyName, object[] values);
void In(string propertyName, ICollection values);
void InG<T>(string propertyName, ICollection<T> values);
void IsNull(string propertyName);
void EqProperty(string propertyName, string otherPropertyName);
void NotEqProperty(string propertyName, string otherPropertyName);
void GtProperty(string propertyName, string otherPropertyName);
void GeProperty(string propertyName, string otherPropertyName);
void LtProperty(string propertyName, string otherPropertyName);
void LeProperty(string propertyName, string otherPropertyName);
void IsNotNull(string propertyName);
void IsNotEmpty(string propertyName);
void IsEmpty(string propertyName);
void And(Action<IExpressionFactory> lhs, Action<IExpressionFactory> rhs);
void Or(Action<IExpressionFactory> lhs, Action<IExpressionFactory> rhs);
void Not(Action<IExpressionFactory> expression);
void Conjunction(Action<IExpressionFactory> expression, params Action<IExpressionFactory>[] otherExpressions);
void Disjunction(Action<IExpressionFactory> expression, params Action<IExpressionFactory>[] otherExpressions);
void AllEq(IDictionary propertyNameValues);
void NaturalId();
}
public enum MatchMode {
Exact,
Start,
End,
Anywhere
}
}

View File

@@ -0,0 +1,9 @@
namespace Orchard.ContentManagement {
public interface ISortFactory {
ISortFactory WithRecord(string recordName);
ISortFactory WithVersionRecord(string recordName);
void Asc(string propertyName);
void Desc(string propertyName);
}
}

View File

@@ -169,6 +169,7 @@
<Compile Include="ContentManagement\ContentIdentity.cs" />
<Compile Include="ContentManagement\ContentItemBehavior.cs" />
<Compile Include="ContentManagement\ContentPartBehavior.cs" />
<Compile Include="ContentManagement\ISortFactory.cs" />
<Compile Include="ContentManagement\DefaultContentDisplay.cs" />
<Compile Include="ContentManagement\Drivers\ContentShapeResult.cs" />
<Compile Include="ContentManagement\FieldStorage\IFieldStorageEvents.cs" />
@@ -178,6 +179,7 @@
<Compile Include="ContentManagement\Handlers\ImportContentContext.cs" />
<Compile Include="ContentManagement\Handlers\TitleAspectHandler.cs" />
<Compile Include="ContentManagement\IContentBehavior.cs" />
<Compile Include="ContentManagement\IExpressionFactory.cs" />
<Compile Include="ContentManagement\ImportContentSession.cs" />
<Compile Include="ContentManagement\MetaData\Services\ISettingsFormatter.cs" />
<Compile Include="ContentManagement\QueryHints.cs" />