Updating display/shape services

--HG--
branch : mvc3p1
This commit is contained in:
Louis DeJardin
2010-08-25 21:42:53 -07:00
parent d16a0875a0
commit a744a3221f
22 changed files with 286 additions and 41 deletions

View File

@@ -1 +1 @@
ef6e8cd4054851538d62655df874721889180b78 Clay 627628209d0b427eb6446e22da5ac046b2cd77c9 Clay

Binary file not shown.

Binary file not shown.

View File

@@ -26,7 +26,7 @@ namespace Orchard.Tests.DisplayManagement {
displayHelper.Invoke("Pager", ArgsUtility.Positional(1, 2, 3, 4)); displayHelper.Invoke("Pager", ArgsUtility.Positional(1, 2, 3, 4));
shapeFactory.Verify(sf=>sf.Build("Pager", It.IsAny<INamedEnumerable<object>>())); shapeFactory.Verify(sf=>sf.Build("Pager", It.IsAny<INamedEnumerable<object>>()));
displayManager.Verify(dm => dm.Execute(It.IsAny<Shape>(), viewContext, null)); //displayManager.Verify(dm => dm.Execute(It.IsAny<Shape>(), viewContext, null));
} }
[Test] [Test]
public void DisplayingShapeWithArgumentsDynamically() { public void DisplayingShapeWithArgumentsDynamically() {
@@ -41,7 +41,7 @@ namespace Orchard.Tests.DisplayManagement {
display.Pager(1, 2, 3, 4); display.Pager(1, 2, 3, 4);
shapeFactory.Verify(sf => sf.Build("Pager", It.IsAny<INamedEnumerable<object>>())); shapeFactory.Verify(sf => sf.Build("Pager", It.IsAny<INamedEnumerable<object>>()));
displayManager.Verify(dm => dm.Execute(It.IsAny<Shape>(), viewContext, null)); //displayManager.Verify(dm => dm.Execute(It.IsAny<Shape>(), viewContext, null));
} }
@@ -58,7 +58,7 @@ namespace Orchard.Tests.DisplayManagement {
var outline = new Shape { Attributes = new ShapeAttributes { Type = "Outline" } }; var outline = new Shape { Attributes = new ShapeAttributes { Type = "Outline" } };
display(outline); display(outline);
displayManager.Verify(dm => dm.Execute(outline, viewContext, null)); //displayManager.Verify(dm => dm.Execute(outline, viewContext, null));
} }
} }
} }

View File

@@ -1,5 +1,8 @@
using System;
using System.Dynamic;
using System.Web.Mvc; using System.Web.Mvc;
using Orchard.DevTools.Models; using Orchard.DevTools.Models;
using Orchard.DisplayManagement;
using Orchard.Localization; using Orchard.Localization;
using Orchard.Mvc.ViewModels; using Orchard.Mvc.ViewModels;
using Orchard.Themes; using Orchard.Themes;
@@ -12,11 +15,14 @@ namespace Orchard.DevTools.Controllers {
public class HomeController : Controller { public class HomeController : Controller {
private readonly INotifier _notifier; private readonly INotifier _notifier;
public HomeController(INotifier notifier) { public HomeController(INotifier notifier, IShapeHelperFactory shapeHelperFactory) {
_notifier = notifier; _notifier = notifier;
T = NullLocalizer.Instance; T = NullLocalizer.Instance;
New = shapeHelperFactory.CreateShapeHelper();
} }
dynamic New { get; set; }
public Localizer T { get; set; } public Localizer T { get; set; }
public ActionResult Index() { public ActionResult Index() {
@@ -45,5 +51,26 @@ namespace Orchard.DevTools.Controllers {
public ActionResult SimpleNoTheme() { public ActionResult SimpleNoTheme() {
return View("Simple", new Simple { Title = "This is not themed", Quantity = 5 }); return View("Simple", new Simple { Title = "This is not themed", Quantity = 5 });
} }
public ActionResult UsingShapes() {
ViewModel.Page = New.Page()
.Main(New.Zone(typeof(Array), Name: "Main"))
.Messages(New.Zone(typeof(Array), Name: "Main"))
.Sidebar(New.Zone(typeof(Array), Name: "Main"));
ViewModel.Page.Messages.Add(
New.Message(Content: T("This is a test"), Severity: "Really bad!!!"));
var model = New.Explosion(Height: 100, Width: 200);
return View("UsingShapes", model);
}
public static string Break(dynamic view) {
return view.Model.Box.Title;
}
}
public class MyViewModel {
public dynamic Box { get; set; }
} }
} }

View File

@@ -43,6 +43,7 @@
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\lib\nhprof\HibernatingRhinos.Profiler.Appender.dll</HintPath> <HintPath>..\..\..\..\lib\nhprof\HibernatingRhinos.Profiler.Appender.dll</HintPath>
</Reference> </Reference>
<Reference Include="Microsoft.CSharp" />
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Data" /> <Reference Include="System.Data" />
<Reference Include="System.ComponentModel.DataAnnotations"> <Reference Include="System.ComponentModel.DataAnnotations">
@@ -85,6 +86,7 @@
<Content Include="ScaffoldingTemplates\DataMigration.txt" /> <Content Include="ScaffoldingTemplates\DataMigration.txt" />
<Compile Include="Services\ScaffoldingCommandInterpreter.cs" /> <Compile Include="Services\ScaffoldingCommandInterpreter.cs" />
<Compile Include="Settings\DevToolsSettings.cs" /> <Compile Include="Settings\DevToolsSettings.cs" />
<Compile Include="Shapes.cs" />
<Compile Include="ViewModels\CommandsExecuteViewModel.cs" /> <Compile Include="ViewModels\CommandsExecuteViewModel.cs" />
<Compile Include="ViewModels\ContentIndexViewModel.cs" /> <Compile Include="ViewModels\ContentIndexViewModel.cs" />
<Compile Include="ViewModels\ContentDetailsViewModel.cs" /> <Compile Include="ViewModels\ContentDetailsViewModel.cs" />
@@ -122,7 +124,9 @@
<Name>Orchard.Core</Name> <Name>Orchard.Core</Name>
</ProjectReference> </ProjectReference>
</ItemGroup> </ItemGroup>
<ItemGroup /> <ItemGroup>
<None Include="Views\Home\UsingShapes.cshtml" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" /> <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. <!-- To modify your build process, add your task inside one of the targets below and uncomment it.

View File

@@ -0,0 +1,45 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Orchard.DisplayManagement;
namespace Orchard.DevTools {
public class Shapes : IShapeProvider {
public IHtmlString Title(dynamic text) {
return new HtmlString("<h2>" + text + "</h2>");
}
public IHtmlString Explosion(int Height, int Width) {
return new HtmlString(string.Format("<div>Boom {0}x{1}</div>", Height, Width));
}
public IHtmlString Page(dynamic Display, dynamic Shape) {
return Display(Shape.Sidebar, Shape.Messages);
}
public IHtmlString Zone(dynamic Display, dynamic Shape) {
var tag = new TagBuilder("div");
tag.GenerateId("zone-" + Shape.Name);
tag.AddCssClass("zone-" + Shape.Name);
tag.AddCssClass("zone");
tag.InnerHtml = Smash(DisplayAll(Display, Shape)).ToString();
return new HtmlString(tag.ToString());
}
public IHtmlString Message(dynamic Display, object Content, string Severity) {
return Display(Severity, ": ", Content);
}
private static IHtmlString Smash(IEnumerable<IHtmlString> contents) {
return new HtmlString(contents.Aggregate("", (a, b) => a + b));
}
static IEnumerable<IHtmlString> DisplayAll(dynamic Display, dynamic Shape) {
foreach (var item in Shape) {
yield return Display(item);
}
}
}
}

View File

@@ -0,0 +1,8 @@
<div>
@Display.Title(text:"This is everything")
@Display(Model)
@Display(View.Page)
</div>

View File

@@ -11,6 +11,9 @@ using Orchard.ContentManagement.MetaData.Builders;
using Orchard.Data.Migration.Interpreters; using Orchard.Data.Migration.Interpreters;
using Orchard.Data.Providers; using Orchard.Data.Providers;
using Orchard.Data.Migration; using Orchard.Data.Migration;
using Orchard.DisplayManagement;
using Orchard.DisplayManagement.Secondary;
using Orchard.DisplayManagement.Shapes;
using Orchard.Environment.Extensions; using Orchard.Environment.Extensions;
using Orchard.Localization; using Orchard.Localization;
using Orchard.Mvc; using Orchard.Mvc;
@@ -58,6 +61,11 @@ namespace Orchard.Setup {
builder.RegisterType<DefaultDataMigrationInterpreter>().As<IDataMigrationInterpreter>().InstancePerLifetimeScope(); builder.RegisterType<DefaultDataMigrationInterpreter>().As<IDataMigrationInterpreter>().InstancePerLifetimeScope();
builder.RegisterType<DataMigrationManager>().As<IDataMigrationManager>().InstancePerLifetimeScope(); builder.RegisterType<DataMigrationManager>().As<IDataMigrationManager>().InstancePerLifetimeScope();
// in progress - adding services for display/shape support in setup
builder.RegisterType<DisplayHelperFactory>().As<IDisplayHelperFactory>();
builder.RegisterType<DefaultDisplayManager>().As<IDisplayManager>();
builder.RegisterType<DefaultShapeBuilder>().As<IShapeBuilder>();
builder.RegisterType<DefaultShapeTableFactory>().As<IShapeTableFactory>();
} }

View File

@@ -79,7 +79,9 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Orchard.ArchiveLater", "Orc
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Nested", "Nested", "{704716AC-45CC-4421-AD1B-73BA833C6825}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Nested", "Nested", "{704716AC-45CC-4421-AD1B-73BA833C6825}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ClaySharp", "..\nested\Clay\src\ClaySharp\ClaySharp.csproj", "{76BCD43B-7BA5-4B63-B1E1-861641CA2686}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ClaySharp", "..\Clay\src\ClaySharp\ClaySharp.csproj", "{76BCD43B-7BA5-4B63-B1E1-861641CA2686}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ClaySharp.Tests", "..\Clay\src\ClaySharp.Tests\ClaySharp.Tests.csproj", "{10369238-A590-48BF-8D3E-E83EB6F0C931}"
EndProject EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -437,6 +439,16 @@ Global
{76BCD43B-7BA5-4B63-B1E1-861641CA2686}.FxCop|Any CPU.Build.0 = Release|Any CPU {76BCD43B-7BA5-4B63-B1E1-861641CA2686}.FxCop|Any CPU.Build.0 = Release|Any CPU
{76BCD43B-7BA5-4B63-B1E1-861641CA2686}.Release|Any CPU.ActiveCfg = Release|Any CPU {76BCD43B-7BA5-4B63-B1E1-861641CA2686}.Release|Any CPU.ActiveCfg = Release|Any CPU
{76BCD43B-7BA5-4B63-B1E1-861641CA2686}.Release|Any CPU.Build.0 = Release|Any CPU {76BCD43B-7BA5-4B63-B1E1-861641CA2686}.Release|Any CPU.Build.0 = Release|Any CPU
{10369238-A590-48BF-8D3E-E83EB6F0C931}.CodeCoverage|Any CPU.ActiveCfg = Release|Any CPU
{10369238-A590-48BF-8D3E-E83EB6F0C931}.CodeCoverage|Any CPU.Build.0 = Release|Any CPU
{10369238-A590-48BF-8D3E-E83EB6F0C931}.Coverage|Any CPU.ActiveCfg = Release|Any CPU
{10369238-A590-48BF-8D3E-E83EB6F0C931}.Coverage|Any CPU.Build.0 = Release|Any CPU
{10369238-A590-48BF-8D3E-E83EB6F0C931}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{10369238-A590-48BF-8D3E-E83EB6F0C931}.Debug|Any CPU.Build.0 = Debug|Any CPU
{10369238-A590-48BF-8D3E-E83EB6F0C931}.FxCop|Any CPU.ActiveCfg = Release|Any CPU
{10369238-A590-48BF-8D3E-E83EB6F0C931}.FxCop|Any CPU.Build.0 = Release|Any CPU
{10369238-A590-48BF-8D3E-E83EB6F0C931}.Release|Any CPU.ActiveCfg = Release|Any CPU
{10369238-A590-48BF-8D3E-E83EB6F0C931}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
@@ -474,5 +486,6 @@ Global
{0DFA2E10-96C8-4E05-BC10-B710B97ECCDE} = {383DBA32-4A3E-48D1-AAC3-75377A694452} {0DFA2E10-96C8-4E05-BC10-B710B97ECCDE} = {383DBA32-4A3E-48D1-AAC3-75377A694452}
{E65E5633-C0FF-453C-A906-481C14F969D6} = {E75A4CE4-CAA6-41E4-B951-33ACC60DC77C} {E65E5633-C0FF-453C-A906-481C14F969D6} = {E75A4CE4-CAA6-41E4-B951-33ACC60DC77C}
{76BCD43B-7BA5-4B63-B1E1-861641CA2686} = {704716AC-45CC-4421-AD1B-73BA833C6825} {76BCD43B-7BA5-4B63-B1E1-861641CA2686} = {704716AC-45CC-4421-AD1B-73BA833C6825}
{10369238-A590-48BF-8D3E-E83EB6F0C931} = {704716AC-45CC-4421-AD1B-73BA833C6825}
EndGlobalSection EndGlobalSection
EndGlobal EndGlobal

View File

@@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Web;
using System.Web.Mvc; using System.Web.Mvc;
using ClaySharp; using ClaySharp;
using Orchard.DisplayManagement.Shapes; using Orchard.DisplayManagement.Shapes;
@@ -31,12 +32,31 @@ namespace Orchard.DisplayManagement {
return ShapeTypeExecute(name, parameters); return ShapeTypeExecute(name, parameters);
} }
if (parameters.Positional.Count() == 1 && parameters.Positional.All(arg => arg is Shape)) { if (parameters.Positional.Count() == 1) {
var shape = (Shape)parameters.Positional.Single(); return ShapeExecute(parameters.Positional.Single());
return ShapeExecute(shape);
} }
throw new NotImplementedException("Need to handle multiple shapes, as well as other object types"); if (parameters.Positional.Any()) {
return new Combined(ShapeExecute(parameters.Positional));
}
// zero args - no display to execute
return null;
}
public class Combined : IHtmlString {
private readonly IEnumerable<object> _fragments;
public Combined(IEnumerable<object> fragments) {
_fragments = fragments;
}
public string ToHtmlString() {
return _fragments.Aggregate("", (a, b) => a + b);
}
public override string ToString() {
return ToHtmlString();
}
} }
private object ShapeTypeExecute(string name, INamedEnumerable<object> parameters) { private object ShapeTypeExecute(string name, INamedEnumerable<object> parameters) {
@@ -44,8 +64,13 @@ namespace Orchard.DisplayManagement {
return ShapeExecute(shape); return ShapeExecute(shape);
} }
public object ShapeExecute(Shape shape) { public object ShapeExecute(object shape) {
return _displayManager.Execute(shape, ViewContext, ViewDataContainer); var context = new DisplayContext { Display = this, Value = shape, ViewContext = ViewContext };
return _displayManager.Execute(context);
}
public IEnumerable<object> ShapeExecute(IEnumerable<object> shapes) {
return shapes.Select(ShapeExecute).ToArray();
} }
} }
} }

View File

@@ -1,7 +1,7 @@
using System.Web.Mvc; using System.Web.Mvc;
namespace Orchard.DisplayManagement { namespace Orchard.DisplayManagement {
public interface IDisplayHelperFactory : ISingletonDependency { public interface IDisplayHelperFactory : IDependency {
DisplayHelper CreateDisplayHelper(ViewContext viewContext, IViewDataContainer viewDataContainer); DisplayHelper CreateDisplayHelper(ViewContext viewContext, IViewDataContainer viewDataContainer);
} }
} }

View File

@@ -1,5 +1,5 @@
namespace Orchard.DisplayManagement { namespace Orchard.DisplayManagement {
public interface IShapeHelperFactory : ISingletonDependency { public interface IShapeHelperFactory : IDependency {
ShapeHelper CreateShapeHelper(); ShapeHelper CreateShapeHelper();
} }
} }

View File

@@ -1,12 +1,13 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Web;
using System.Web.Mvc; using System.Web.Mvc;
using ClaySharp; using ClaySharp;
using Orchard.DisplayManagement.Shapes; using Orchard.DisplayManagement.Shapes;
namespace Orchard.DisplayManagement { namespace Orchard.DisplayManagement {
public interface IDisplayManager : ISingletonDependency { public interface IDisplayManager : IDependency {
object Execute(Shape shape, ViewContext viewContext, IViewDataContainer viewDataContainer); IHtmlString Execute(DisplayContext context);
} }
} }

View File

@@ -1,5 +1,10 @@
using System.Web; using System;
using System.Dynamic;
using System.Linq.Expressions;
using System.Runtime.CompilerServices;
using System.Web;
using System.Web.Mvc; using System.Web.Mvc;
using Microsoft.CSharp.RuntimeBinder;
using Orchard.DisplayManagement.Shapes; using Orchard.DisplayManagement.Shapes;
using Orchard.Localization; using Orchard.Localization;
@@ -7,6 +12,8 @@ namespace Orchard.DisplayManagement.Secondary {
public class DefaultDisplayManager : IDisplayManager { public class DefaultDisplayManager : IDisplayManager {
private readonly IShapeTableFactory _shapeTableFactory; private readonly IShapeTableFactory _shapeTableFactory;
private static CallSite<Func<CallSite, object, Shape>> _convertAsShapeCallsite;
public DefaultDisplayManager(IShapeTableFactory shapeTableFactory) { public DefaultDisplayManager(IShapeTableFactory shapeTableFactory) {
_shapeTableFactory = shapeTableFactory; _shapeTableFactory = shapeTableFactory;
T = NullLocalizer.Instance; T = NullLocalizer.Instance;
@@ -14,19 +21,72 @@ namespace Orchard.DisplayManagement.Secondary {
public Localizer T { get; set; } public Localizer T { get; set; }
public object Execute(Shape shape, ViewContext viewContext, IViewDataContainer viewDataContainer) {
ShapeAttributes shapeAttributes = ((dynamic)shape).Attributes; public IHtmlString Execute(DisplayContext context) {
if (_convertAsShapeCallsite == null) {
_convertAsShapeCallsite = CallSite<Func<CallSite, object, Shape>>.Create(
new ForgivingConvertBinder(
(ConvertBinder)Binder.Convert(
CSharpBinderFlags.ConvertExplicit | CSharpBinderFlags.CheckedContext,
typeof(Shape),
null/*typeof(DefaultDisplayManager)*/)));
}
var shape = _convertAsShapeCallsite.Target(_convertAsShapeCallsite, context.Value);
// non-shape arguements are returned as a no-op
if (shape == null)
return CoerceHtmlString(context.Value);
var shapeAttributes = shape.Attributes;
// can't really cope with a shape that has no type information
if (shapeAttributes == null || string.IsNullOrEmpty(shapeAttributes.Type))
return CoerceHtmlString(context.Value);
var shapeTable = _shapeTableFactory.CreateShapeTable(); var shapeTable = _shapeTableFactory.CreateShapeTable();
ShapeTable.Entry entry; ShapeTable.Entry entry;
if (shapeTable.Entries.TryGetValue(shapeAttributes.Type, out entry)) { if (shapeTable.Entries.TryGetValue(shapeAttributes.Type, out entry)) {
return Process(entry, shape, viewContext, viewDataContainer); return Process(entry, shape, context);
} }
throw new OrchardException(T("Shape name not found")); throw new OrchardException(T("Shape type {0} not found", shapeAttributes.Type));
} }
private object Process(ShapeTable.Entry entry, Shape shape, ViewContext viewContext, IViewDataContainer viewDataContainer) { private IHtmlString CoerceHtmlString(object value) {
var displayContext = new DisplayContext { ViewContext = viewContext, Shape = shape }; if (value == null)
return entry.Target(displayContext); return null;
var result = value as IHtmlString;
if (result != null)
return result;
return new HtmlString(HttpUtility.HtmlEncode(value));
}
private IHtmlString Process(ShapeTable.Entry entry, Shape shape, DisplayContext context) {
return CoerceHtmlString(entry.Target(context));
}
class ForgivingConvertBinder : ConvertBinder {
private readonly ConvertBinder _innerBinder;
public ForgivingConvertBinder(ConvertBinder innerBinder)
: base(innerBinder.ReturnType, innerBinder.Explicit) {
_innerBinder = innerBinder;
}
public override DynamicMetaObject FallbackConvert(DynamicMetaObject target, DynamicMetaObject errorSuggestion) {
// adjust the normal csharp convert binder to allow failure to become null.
// this causes the same net effect as the "as" keyword, but may be applied to dynamic objects
return _innerBinder.FallbackConvert(
target,
errorSuggestion ?? new DynamicMetaObject(Expression.Default(_innerBinder.ReturnType), GetTypeRestriction(target)));
}
static BindingRestrictions GetTypeRestriction(DynamicMetaObject obj) {
if ((obj.Value == null) && obj.HasValue) {
return BindingRestrictions.GetInstanceRestriction(obj.Expression, null);
}
return BindingRestrictions.GetTypeRestriction(obj.Expression, obj.LimitType);
}
} }
} }
} }

View File

@@ -1,18 +1,50 @@
using System.Linq; using System;
using System.Linq;
using ClaySharp; using ClaySharp;
namespace Orchard.DisplayManagement.Shapes { namespace Orchard.DisplayManagement.Shapes {
public class DefaultShapeBuilder : IShapeBuilder { public class DefaultShapeBuilder : IShapeBuilder {
public Shape Build(string shapeType, INamedEnumerable<object> parameters) { public Shape Build(string shapeType, INamedEnumerable<object> parameters) {
var shape = ClayActivator.CreateInstance<Shape>(new IClayBehavior[]{
new ClaySharp.Behaviors.InterfaceProxyBehavior(), var positional = parameters.Positional;
new ClaySharp.Behaviors.PropBehavior(),
new ClaySharp.Behaviors.NilResultBehavior()}); var baseType = positional.Take(1).OfType<Type>().SingleOrDefault();
if (baseType == null) {
// default to common base class
baseType = typeof(Shape);
}
else {
// consume the first argument
positional = positional.Skip(1);
}
IClayBehavior[] behaviors;
if (baseType == typeof(Array)) {
// array is a hint - not an intended base class
baseType = typeof (Shape);
behaviors = new IClayBehavior[] {
new ClaySharp.Behaviors.InterfaceProxyBehavior(),
new ClaySharp.Behaviors.PropBehavior(),
new ClaySharp.Behaviors.ArrayBehavior(),
new ClaySharp.Behaviors.NilResultBehavior()
};
}
else {
behaviors = new IClayBehavior[] {
new ClaySharp.Behaviors.InterfaceProxyBehavior(),
new ClaySharp.Behaviors.PropBehavior(),
new ClaySharp.Behaviors.NilResultBehavior()
};
}
// consideration - types without default constructors could consume positional arguments?
var shape = ClayActivator.CreateInstance(baseType, behaviors);
shape.Attributes = new ShapeAttributes { Type = shapeType }; shape.Attributes = new ShapeAttributes { Type = shapeType };
if (parameters.Positional.Any()) { // only one non-Type, non-named argument is allowed
var initializer = parameters.Positional.Single(); var initializer = positional.SingleOrDefault();
if (initializer != null) {
foreach (var prop in initializer.GetType().GetProperties()) { foreach (var prop in initializer.GetType().GetProperties()) {
shape[prop.Name] = prop.GetValue(initializer, null); shape[prop.Name] = prop.GetValue(initializer, null);
} }

View File

@@ -1,7 +1,7 @@
using ClaySharp; using ClaySharp;
namespace Orchard.DisplayManagement.Shapes { namespace Orchard.DisplayManagement.Shapes {
public interface IShapeBuilder { public interface IShapeBuilder : IDependency {
Shape Build(string shapeType, INamedEnumerable<object> parameters); Shape Build(string shapeType, INamedEnumerable<object> parameters);
} }
} }

View File

@@ -23,12 +23,31 @@ namespace Orchard.DisplayManagement {
var provider = shapeProvider; var provider = shapeProvider;
yield return new ShapeTable.Entry { yield return new ShapeTable.Entry {
ShapeType = methodInfo.Name, ShapeType = methodInfo.Name,
Target = ctx => info.Invoke(provider, new object[0]) Target = ctx => PerformInvoke(ctx, info, provider)
}; };
} }
} }
} }
private object PerformInvoke(DisplayContext displayContext, MethodInfo methodInfo, IShapeProvider shapeProvider) {
// oversimplification for the sake of evolving
dynamic shape = displayContext.Value;
var arguments = methodInfo.GetParameters()
.Select(parameter => BindParameter(displayContext, parameter));
return methodInfo.Invoke(shapeProvider, arguments.ToArray());
}
private object BindParameter(DisplayContext displayContext, ParameterInfo parameter) {
if (parameter.Name == "Shape")
return displayContext.Value;
if (parameter.Name == "Display")
return displayContext.Display;
return ((dynamic)(displayContext.Value))[parameter.Name];
}
static bool IsAcceptableMethod(MethodInfo methodInfo) { static bool IsAcceptableMethod(MethodInfo methodInfo) {
if (methodInfo.IsSpecialName) if (methodInfo.IsSpecialName)
return false; return false;

View File

@@ -8,7 +8,8 @@ using Orchard.DisplayManagement.Shapes;
namespace Orchard.DisplayManagement { namespace Orchard.DisplayManagement {
public class DisplayContext { public class DisplayContext {
public DisplayHelper Display { get; set; }
public ViewContext ViewContext { get; set; } public ViewContext ViewContext { get; set; }
public Shape Shape { get; set; } public object Value { get; set; }
} }
} }

View File

@@ -1,3 +1,3 @@
namespace Orchard.DisplayManagement { namespace Orchard.DisplayManagement {
public interface IShapeProvider : ISingletonDependency{} public interface IShapeProvider : IDependency{}
} }

View File

@@ -4,7 +4,7 @@ using System.Linq;
using System.Text; using System.Text;
namespace Orchard.DisplayManagement { namespace Orchard.DisplayManagement {
public interface IShapeTableFactory : ISingletonDependency { public interface IShapeTableFactory : IDependency {
ShapeTable CreateShapeTable(); ShapeTable CreateShapeTable();
} }
} }

View File

@@ -77,9 +77,6 @@
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
<HintPath>..\..\lib\Castle Windsor 2.0\bin\Castle.DynamicProxy2.dll</HintPath> <HintPath>..\..\lib\Castle Windsor 2.0\bin\Castle.DynamicProxy2.dll</HintPath>
</Reference> </Reference>
<Reference Include="ClaySharp">
<HintPath>..\..\lib\clay\ClaySharp.dll</HintPath>
</Reference>
<Reference Include="FluentNHibernate, Version=1.0.0.593, Culture=neutral, PublicKeyToken=8aa435e3cb308880, processorArchitecture=MSIL"> <Reference Include="FluentNHibernate, Version=1.0.0.593, Culture=neutral, PublicKeyToken=8aa435e3cb308880, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
<HintPath>..\..\lib\fluentnhibernate\FluentNHibernate.dll</HintPath> <HintPath>..\..\lib\fluentnhibernate\FluentNHibernate.dll</HintPath>
@@ -814,7 +811,12 @@
<Install>true</Install> <Install>true</Install>
</BootstrapperPackage> </BootstrapperPackage>
</ItemGroup> </ItemGroup>
<ItemGroup /> <ItemGroup>
<ProjectReference Include="..\..\Clay\src\ClaySharp\ClaySharp.csproj">
<Project>{76BCD43B-7BA5-4B63-B1E1-861641CA2686}</Project>
<Name>ClaySharp</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets. Other similar extension points exist, see Microsoft.Common.targets.