mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-12-02 11:44:41 +08:00
Adding a PartDriver concept to try and drive down complexity
--HG-- extra : convert_revision : svn%3A5ff7c347-ad56-4c35-b696-ccb81de16e03/trunk%4043668
This commit is contained in:
101
src/Orchard.Tests/Models/PartDriverHandlerTests.cs
Normal file
101
src/Orchard.Tests/Models/PartDriverHandlerTests.cs
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using Autofac;
|
||||||
|
using Autofac.Builder;
|
||||||
|
using Autofac.Modules;
|
||||||
|
using Moq;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using Orchard.Models;
|
||||||
|
using Orchard.Models.Driver;
|
||||||
|
using Orchard.Models.ViewModels;
|
||||||
|
|
||||||
|
namespace Orchard.Tests.Models {
|
||||||
|
[TestFixture]
|
||||||
|
public class PartDriverHandlerTests {
|
||||||
|
private IContainer _container;
|
||||||
|
|
||||||
|
[SetUp]
|
||||||
|
public void Init() {
|
||||||
|
var builder = new ContainerBuilder();
|
||||||
|
builder.RegisterModule(new ImplicitCollectionSupportModule());
|
||||||
|
builder.Register<PartDriverHandler>().As<IContentHandler>();
|
||||||
|
_container = builder.Build();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void DriverHandlerShouldNotThrowException() {
|
||||||
|
var contentHandler = _container.Resolve<IContentHandler>();
|
||||||
|
contentHandler.BuildDisplayModel(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void AllDriversShouldBeCalled() {
|
||||||
|
var driver1 = new Mock<IPartDriver>();
|
||||||
|
var driver2 = new Mock<IPartDriver>();
|
||||||
|
_container.Build(x => {
|
||||||
|
x.Register(driver1.Object);
|
||||||
|
x.Register(driver2.Object);
|
||||||
|
});
|
||||||
|
var contentHandler = _container.Resolve<IContentHandler>();
|
||||||
|
|
||||||
|
var ctx = new BuildDisplayModelContext(new ItemDisplayModel(new ContentItem()), null, null);
|
||||||
|
|
||||||
|
driver1.Verify(x => x.BuildDisplayModel(ctx), Times.Never());
|
||||||
|
contentHandler.BuildDisplayModel(ctx);
|
||||||
|
driver1.Verify(x => x.BuildDisplayModel(ctx));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestDriverCanAddDisplay() {
|
||||||
|
var driver = new StubDriver();
|
||||||
|
_container.Build(x => x.Register(driver).As<IPartDriver>());
|
||||||
|
|
||||||
|
var contentHandler = _container.Resolve<IContentHandler>();
|
||||||
|
|
||||||
|
var item = new ContentItem();
|
||||||
|
item.Weld(new StubPart());
|
||||||
|
|
||||||
|
var ctx = new BuildDisplayModelContext(new ItemDisplayModel(item), null, null);
|
||||||
|
Assert.That(ctx.DisplayModel.Displays.Count(), Is.EqualTo(0));
|
||||||
|
contentHandler.BuildDisplayModel(ctx);
|
||||||
|
Assert.That(ctx.DisplayModel.Displays.Count(), Is.EqualTo(1));
|
||||||
|
Assert.That(ctx.DisplayModel.Displays.Single().Prefix, Is.EqualTo("Stub"));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private class StubDriver : PartDriver<StubPart> {
|
||||||
|
protected override string Prefix {
|
||||||
|
get { return "Stub"; }
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override DriverResult Display(StubPart part, string groupName, string displayType) {
|
||||||
|
var viewModel = new StubViewModel { Foo = string.Join(",", part.Foo) };
|
||||||
|
return PartialView(viewModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override DriverResult Editor(StubPart part, string groupName) {
|
||||||
|
var viewModel = new StubViewModel { Foo = string.Join(",", part.Foo) };
|
||||||
|
return PartialView(viewModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override DriverResult Editor(StubPart part, string groupName, IUpdateModel updater) {
|
||||||
|
var viewModel = new StubViewModel { Foo = string.Join(",", part.Foo) };
|
||||||
|
updater.TryUpdateModel(viewModel, Prefix, null, null);
|
||||||
|
part.Foo = viewModel.Foo.Split(new[] {','}).Select(x => x.Trim()).ToArray();
|
||||||
|
return PartialView(viewModel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class StubPart : ContentPart {
|
||||||
|
public string[] Foo { get; set; }
|
||||||
|
}
|
||||||
|
private class StubViewModel {
|
||||||
|
[Required]
|
||||||
|
public string Foo { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -66,6 +66,9 @@
|
|||||||
<HintPath>..\..\lib\nunit\nunit.framework.dll</HintPath>
|
<HintPath>..\..\lib\nunit\nunit.framework.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
|
<Reference Include="System.ComponentModel.DataAnnotations">
|
||||||
|
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
||||||
|
</Reference>
|
||||||
<Reference Include="System.Configuration" />
|
<Reference Include="System.Configuration" />
|
||||||
<Reference Include="System.Core">
|
<Reference Include="System.Core">
|
||||||
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
||||||
@@ -117,6 +120,7 @@
|
|||||||
<Compile Include="Models\DefaultModelManagerTests.cs" />
|
<Compile Include="Models\DefaultModelManagerTests.cs" />
|
||||||
<Compile Include="Models\Drivers\ModelBuilderTests.cs" />
|
<Compile Include="Models\Drivers\ModelBuilderTests.cs" />
|
||||||
<Compile Include="Models\Drivers\ModelDriverTests.cs" />
|
<Compile Include="Models\Drivers\ModelDriverTests.cs" />
|
||||||
|
<Compile Include="Models\PartDriverHandlerTests.cs" />
|
||||||
<Compile Include="Models\Stubs\Alpha.cs" />
|
<Compile Include="Models\Stubs\Alpha.cs" />
|
||||||
<Compile Include="Models\Stubs\AlphaHandler.cs" />
|
<Compile Include="Models\Stubs\AlphaHandler.cs" />
|
||||||
<Compile Include="Models\Stubs\Beta.cs" />
|
<Compile Include="Models\Stubs\Beta.cs" />
|
||||||
|
|||||||
137
src/Orchard/Models/PartDriver.cs
Normal file
137
src/Orchard/Models/PartDriver.cs
Normal file
@@ -0,0 +1,137 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using JetBrains.Annotations;
|
||||||
|
using Orchard.Logging;
|
||||||
|
using Orchard.Models.Driver;
|
||||||
|
using Orchard.Models.ViewModels;
|
||||||
|
|
||||||
|
namespace Orchard.Models {
|
||||||
|
public interface IPartDriver : IEvents {
|
||||||
|
DriverResult BuildDisplayModel(BuildDisplayModelContext context);
|
||||||
|
DriverResult BuildEditorModel(BuildEditorModelContext context);
|
||||||
|
DriverResult UpdateEditorModel(UpdateEditorModelContext context);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public abstract class PartDriver<TPart> : IPartDriver where TPart : class, IContent {
|
||||||
|
DriverResult IPartDriver.BuildDisplayModel(BuildDisplayModelContext context) {
|
||||||
|
var part = context.ContentItem.As<TPart>();
|
||||||
|
return part == null ? null : BuildDisplayModel(part, context.GroupName, context.DisplayType);
|
||||||
|
}
|
||||||
|
|
||||||
|
DriverResult IPartDriver.BuildEditorModel(BuildEditorModelContext context) {
|
||||||
|
var part = context.ContentItem.As<TPart>();
|
||||||
|
return part == null ? null : BuildEditorModel(part, context.GroupName);
|
||||||
|
}
|
||||||
|
|
||||||
|
DriverResult IPartDriver.UpdateEditorModel(UpdateEditorModelContext context) {
|
||||||
|
var part = context.ContentItem.As<TPart>();
|
||||||
|
return part == null ? null : UpdateEditorModel(part, context.GroupName, context.Updater);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual DriverResult BuildDisplayModel(TPart part, string groupName, string displayType) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual DriverResult BuildEditorModel(TPart part, string groupName) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual DriverResult UpdateEditorModel(TPart part, string groupName, IUpdateModel updater) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual string Prefix { get { return ""; } }
|
||||||
|
|
||||||
|
public TemplateResult PartialView(object model) {
|
||||||
|
return new TemplateResult(model, null, Prefix);
|
||||||
|
}
|
||||||
|
public TemplateResult PartialView(object model, string template) {
|
||||||
|
return new TemplateResult(model, template, Prefix);
|
||||||
|
}
|
||||||
|
public TemplateResult PartialView(object model, string template, string prefix) {
|
||||||
|
return new TemplateResult(model, template, prefix);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class DriverResult {
|
||||||
|
public virtual void Apply(BuildDisplayModelContext context) { }
|
||||||
|
public virtual void Apply(BuildEditorModelContext context) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class TemplateResult : DriverResult {
|
||||||
|
public object Model { get; set; }
|
||||||
|
public string TemplateName { get; set; }
|
||||||
|
public string Prefix { get; set; }
|
||||||
|
|
||||||
|
public TemplateResult(object model, string templateName, string prefix) {
|
||||||
|
Model = model;
|
||||||
|
TemplateName = templateName;
|
||||||
|
Prefix = prefix;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Apply(BuildDisplayModelContext context) {
|
||||||
|
context.AddDisplay(new TemplateViewModel(Model, Prefix) { TemplateName = TemplateName });
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Apply(BuildEditorModelContext context) {
|
||||||
|
context.AddEditor(new TemplateViewModel(Model, Prefix) { TemplateName = TemplateName });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[UsedImplicitly]
|
||||||
|
public class PartDriverHandler : IContentHandler {
|
||||||
|
private readonly IEnumerable<IPartDriver> _drivers;
|
||||||
|
|
||||||
|
public PartDriverHandler(IEnumerable<IPartDriver> drivers) {
|
||||||
|
_drivers = drivers;
|
||||||
|
Logger = NullLogger.Instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ILogger Logger { get; set; }
|
||||||
|
|
||||||
|
System.Collections.Generic.IEnumerable<ContentType> IContentHandler.GetContentTypes() {
|
||||||
|
return Enumerable.Empty<ContentType>();
|
||||||
|
}
|
||||||
|
|
||||||
|
void IContentHandler.Activating(ActivatingContentContext context) { }
|
||||||
|
|
||||||
|
void IContentHandler.Activated(ActivatedContentContext context) { }
|
||||||
|
|
||||||
|
void IContentHandler.Creating(CreateContentContext context) { }
|
||||||
|
|
||||||
|
void IContentHandler.Created(CreateContentContext context) { }
|
||||||
|
|
||||||
|
void IContentHandler.Loading(LoadContentContext context) { }
|
||||||
|
|
||||||
|
void IContentHandler.Loaded(LoadContentContext context) { }
|
||||||
|
|
||||||
|
void IContentHandler.GetItemMetadata(GetItemMetadataContext context) { }
|
||||||
|
|
||||||
|
void IContentHandler.BuildDisplayModel(BuildDisplayModelContext context) {
|
||||||
|
_drivers.Invoke(driver => {
|
||||||
|
var result = driver.BuildDisplayModel(context);
|
||||||
|
if (result != null)
|
||||||
|
result.Apply(context);
|
||||||
|
}, Logger);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IContentHandler.BuildEditorModel(BuildEditorModelContext context) {
|
||||||
|
_drivers.Invoke(driver => {
|
||||||
|
var result = driver.BuildEditorModel(context);
|
||||||
|
if (result != null)
|
||||||
|
result.Apply(context);
|
||||||
|
}, Logger);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IContentHandler.UpdateEditorModel(UpdateEditorModelContext context) {
|
||||||
|
_drivers.Invoke(driver => {
|
||||||
|
var result = driver.UpdateEditorModel(context);
|
||||||
|
if (result != null)
|
||||||
|
result.Apply(context);
|
||||||
|
}, Logger);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -19,6 +19,7 @@ namespace Orchard.Models.ViewModels {
|
|||||||
|
|
||||||
public ItemDisplayModel(ContentItem item) {
|
public ItemDisplayModel(ContentItem item) {
|
||||||
Item = item;
|
Item = item;
|
||||||
|
Displays = Enumerable.Empty<TemplateViewModel>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ContentItem Item {
|
public ContentItem Item {
|
||||||
|
|||||||
@@ -178,6 +178,7 @@
|
|||||||
<Compile Include="Models\ContentPart.cs" />
|
<Compile Include="Models\ContentPart.cs" />
|
||||||
<Compile Include="Models\IContent.cs" />
|
<Compile Include="Models\IContent.cs" />
|
||||||
<Compile Include="Models\IContentQuery.cs" />
|
<Compile Include="Models\IContentQuery.cs" />
|
||||||
|
<Compile Include="Models\PartDriver.cs" />
|
||||||
<Compile Include="Models\Records\ContentItemRecordAlteration.cs" />
|
<Compile Include="Models\Records\ContentItemRecordAlteration.cs" />
|
||||||
<Compile Include="Models\Records\ContentPartRecord.cs" />
|
<Compile Include="Models\Records\ContentPartRecord.cs" />
|
||||||
<Compile Include="Models\Records\ContentPartRecordAlteration.cs" />
|
<Compile Include="Models\Records\ContentPartRecordAlteration.cs" />
|
||||||
|
|||||||
Reference in New Issue
Block a user