start extensibility
This commit is contained in:
@@ -5,7 +5,7 @@ namespace zero.Core.Attributes
|
||||
/// <summary>
|
||||
/// This attribute will allow the usage of custom collection names for Raven collections
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
|
||||
[AttributeUsage(AttributeTargets.Interface | AttributeTargets.Class, AllowMultiple = false)]
|
||||
public class CollectionAttribute : Attribute
|
||||
{
|
||||
public string Name { get; set; }
|
||||
|
||||
@@ -32,9 +32,9 @@ namespace zero.Core.Mapper
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Add<T>() where T : IMapperConfig, new()
|
||||
public void Add<T>() where T : IMapperConfig
|
||||
{
|
||||
T config = new T();
|
||||
T config = Activator.CreateInstance<T>();
|
||||
config.Configure(this);
|
||||
}
|
||||
|
||||
@@ -54,19 +54,19 @@ namespace zero.Core.Mapper
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<TTarget> Map<TSource, TTarget>(TSource source) where TTarget : class, new()
|
||||
public async Task<TTarget> Map<TSource, TTarget>(TSource source)
|
||||
{
|
||||
if (source == null)
|
||||
{
|
||||
return null;
|
||||
return default;
|
||||
}
|
||||
|
||||
return await Map(source, new TTarget());
|
||||
return await Map(source, Activator.CreateInstance<TTarget>());
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<TTarget> Map<TSource, TTarget>(TSource source, TTarget target) where TTarget : class, new()
|
||||
public async Task<TTarget> Map<TSource, TTarget>(TSource source, TTarget target)
|
||||
{
|
||||
if (source == null)
|
||||
{
|
||||
@@ -85,13 +85,13 @@ namespace zero.Core.Mapper
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<IEnumerable<TTarget>> Map<TSource, TTarget>(IEnumerable<TSource> source) where TTarget : class, new()
|
||||
public async Task<IEnumerable<TTarget>> Map<TSource, TTarget>(IEnumerable<TSource> source)
|
||||
{
|
||||
IList<TTarget> target = new List<TTarget>();
|
||||
|
||||
foreach (TSource item in source)
|
||||
{
|
||||
target.Add(await Map(item, new TTarget()));
|
||||
target.Add(await Map(item, Activator.CreateInstance<TTarget>()));
|
||||
}
|
||||
|
||||
return target;
|
||||
@@ -99,13 +99,13 @@ namespace zero.Core.Mapper
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<ListResult<TTarget>> Map<TSource, TTarget>(ListResult<TSource> source) where TTarget : class, new()
|
||||
public async Task<ListResult<TTarget>> Map<TSource, TTarget>(ListResult<TSource> source)
|
||||
{
|
||||
IList<TTarget> target = new List<TTarget>();
|
||||
|
||||
foreach (TSource item in source.Items)
|
||||
{
|
||||
target.Add(await Map(item, new TTarget()));
|
||||
target.Add(await Map(item, Activator.CreateInstance<TTarget>()));
|
||||
}
|
||||
|
||||
return new ListResult<TTarget>(target, source.TotalItems, source.Page, source.PageSize)
|
||||
@@ -116,19 +116,19 @@ namespace zero.Core.Mapper
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<EntityResult<TTarget>> Map<TSource, TTarget>(EntityResult<TSource> source) where TTarget : class, new()
|
||||
public async Task<EntityResult<TTarget>> Map<TSource, TTarget>(EntityResult<TSource> source)
|
||||
{
|
||||
return new EntityResult<TTarget>()
|
||||
{
|
||||
IsSuccess = source.IsSuccess,
|
||||
Errors = source.Errors,
|
||||
Model = await Map(source.Model, new TTarget())
|
||||
Model = await Map(source.Model, Activator.CreateInstance<TTarget>())
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public void CreateMap<TSource, TTarget>(Action<TSource, TTarget> map) where TTarget : class, new()
|
||||
public void CreateMap<TSource, TTarget>(Action<TSource, TTarget> map)
|
||||
{
|
||||
Maps.Add<TSource, TTarget>((source, target) =>
|
||||
{
|
||||
@@ -139,7 +139,7 @@ namespace zero.Core.Mapper
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public void CreateMap<TSource, TTarget>(Func<TSource, TTarget, IAsyncDocumentSession, Task> map) where TTarget : class, new()
|
||||
public void CreateMap<TSource, TTarget>(Func<TSource, TTarget, IAsyncDocumentSession, Task> map)
|
||||
{
|
||||
Maps.Add<TSource, TTarget>(async (source, target) =>
|
||||
{
|
||||
@@ -220,7 +220,7 @@ namespace zero.Core.Mapper
|
||||
public interface IMapper
|
||||
{
|
||||
/// <inheritdoc />
|
||||
void Add<T>() where T : IMapperConfig, new();
|
||||
void Add<T>() where T : IMapperConfig;
|
||||
|
||||
/// <inheritdoc />
|
||||
void Add(Assembly assembly);
|
||||
@@ -228,34 +228,34 @@ namespace zero.Core.Mapper
|
||||
/// <summary>
|
||||
/// Map an object to the target type
|
||||
/// </summary>
|
||||
Task<TTarget> Map<TSource, TTarget>(TSource source) where TTarget : class, new();
|
||||
Task<TTarget> Map<TSource, TTarget>(TSource source);
|
||||
|
||||
/// <summary>
|
||||
/// Map an object to the target type given an already existing target instance
|
||||
/// </summary>
|
||||
Task<TTarget> Map<TSource, TTarget>(TSource source, TTarget target) where TTarget : class, new();
|
||||
Task<TTarget> Map<TSource, TTarget>(TSource source, TTarget target);
|
||||
|
||||
/// <summary>
|
||||
/// Map a list of objects to the target type
|
||||
/// </summary>
|
||||
Task<IEnumerable<TTarget>> Map<TSource, TTarget>(IEnumerable<TSource> source) where TTarget : class, new();
|
||||
Task<IEnumerable<TTarget>> Map<TSource, TTarget>(IEnumerable<TSource> source);
|
||||
|
||||
/// <summary>
|
||||
/// Map a list result containing objects to the target type
|
||||
/// </summary>
|
||||
Task<ListResult<TTarget>> Map<TSource, TTarget>(ListResult<TSource> source) where TTarget : class, new();
|
||||
Task<ListResult<TTarget>> Map<TSource, TTarget>(ListResult<TSource> source);
|
||||
|
||||
/// <summary>
|
||||
/// Map an entity result to the target type
|
||||
/// </summary>
|
||||
Task<EntityResult<TTarget>> Map<TSource, TTarget>(EntityResult<TSource> source) where TTarget : class, new();
|
||||
Task<EntityResult<TTarget>> Map<TSource, TTarget>(EntityResult<TSource> source);
|
||||
|
||||
/// <summary>
|
||||
/// Create a mapping from source to target object
|
||||
/// </summary>
|
||||
void CreateMap<TSource, TTarget>(Action<TSource, TTarget> map) where TTarget : class, new();
|
||||
void CreateMap<TSource, TTarget>(Action<TSource, TTarget> map);
|
||||
|
||||
/// <inheritdoc />
|
||||
void CreateMap<TSource, TTarget>(Func<TSource, TTarget, IAsyncDocumentSession, Task> map) where TTarget : class, new();
|
||||
void CreateMap<TSource, TTarget>(Func<TSource, TTarget, IAsyncDocumentSession, Task> map);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace zero.Core.Options
|
||||
{
|
||||
public class TypeOptions : IZeroCollectionOptions
|
||||
{
|
||||
Dictionary<Type, Type> Items { get; set; } = new Dictionary<Type, Type>();
|
||||
|
||||
internal void Add<T, TTarget>() where TTarget : T
|
||||
{
|
||||
Items[typeof(T)] = typeof(TTarget);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,8 @@
|
||||
using System.Collections.Generic;
|
||||
using FluentValidation;
|
||||
using System.Collections.Generic;
|
||||
using zero.Core.Mapper;
|
||||
using zero.Core.Plugins;
|
||||
using zero.Core.Renderer;
|
||||
|
||||
namespace zero.Core.Options
|
||||
{
|
||||
@@ -19,6 +22,7 @@ namespace zero.Core.Options
|
||||
Settings = new SettingsOptions();
|
||||
Spaces = new SpaceOptions();
|
||||
Mapper = new MapperOptions();
|
||||
Types = new TypeOptions();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -65,6 +69,20 @@ namespace zero.Core.Options
|
||||
|
||||
/// <inheritdoc />
|
||||
public MapperOptions Mapper { get; private set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public TypeOptions Types { get; private set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Extend<T, TTarget>() where TTarget : T
|
||||
{
|
||||
Types.Add<T, TTarget>();
|
||||
}
|
||||
|
||||
public ZeroExtend<T> Extend<T>()
|
||||
{
|
||||
return new ZeroExtend<T>();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -149,10 +167,53 @@ namespace zero.Core.Options
|
||||
/// </summary>
|
||||
MapperOptions Mapper { get; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
TypeOptions Types { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
void Extend<T, TTarget>() where TTarget : T;
|
||||
|
||||
ZeroExtend<T> Extend<T>();
|
||||
|
||||
/// <summary>
|
||||
/// Default settings for the backoffice
|
||||
/// </summary>
|
||||
//IZeroPluginConfiguration Backoffice { get; set; }
|
||||
}
|
||||
|
||||
|
||||
public class ZeroExtend<T>
|
||||
{
|
||||
public ZeroExtend<T> Use<TTarget>() where TTarget : T
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
public ZeroExtend<T> Use<TTarget, TRenderer>()
|
||||
where TTarget : T
|
||||
where TRenderer : IRenderer<T>
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
public ZeroExtend<T> Use<TTarget, TRenderer, TValidator>()
|
||||
where TTarget : T
|
||||
where TRenderer : IRenderer<T>
|
||||
where TValidator : IValidator<T>
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public ZeroExtend<T> Use<TTarget, TRenderer, TValidator, TMapper>()
|
||||
where TTarget : T
|
||||
where TRenderer : IRenderer<T>
|
||||
where TValidator : IValidator<T>
|
||||
where TMapper : IMapperConfig
|
||||
{
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace zero.Core.Renderer
|
||||
}
|
||||
|
||||
|
||||
public abstract class AbstractRenderer<T> : IRenderer<T>, IRenderer where T : new()
|
||||
public abstract class AbstractRenderer<T> : IRenderer<T>, IRenderer
|
||||
{
|
||||
const string METHOD_FIELD = "field";
|
||||
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
using zero.Commerce.Entities;
|
||||
|
||||
namespace zero.Debug.Models
|
||||
{
|
||||
public class SalesChannel : Channel
|
||||
{
|
||||
public string Description { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
using zero.Commerce.Entities;
|
||||
using zero.Core.Renderer;
|
||||
using zero.Debug.Models;
|
||||
|
||||
namespace zero.Commerce.Backoffice
|
||||
{
|
||||
public class SalesChannelRenderer : AbstractRenderer<SalesChannel>
|
||||
{
|
||||
public SalesChannelRenderer() : base()
|
||||
{
|
||||
|
||||
Field(x => x.Name, required: false).Text();
|
||||
|
||||
//Field(x => x.Name, "@ui.name", required: true, noDescription: true).Text();
|
||||
|
||||
//Field(x => x.CheckoutType).State(opts =>
|
||||
//{
|
||||
// opts.Add("@channel.checkout_states.none", ChannelCheckoutType.None);
|
||||
// opts.Add("@channel.checkout_states.order", ChannelCheckoutType.Order);
|
||||
// opts.Add("@channel.checkout_states.request", ChannelCheckoutType.Request);
|
||||
// opts.Add("@channel.checkout_states.both", ChannelCheckoutType.All);
|
||||
//});
|
||||
//Field(x => x.ProductSorting).State(opts =>
|
||||
//{
|
||||
// opts.Add("@channel.sorting_states.relevance", ChannelProductSorting.Relevance);
|
||||
// opts.Add("@channel.sorting_states.new", ChannelProductSorting.New);
|
||||
// opts.Add("@channel.sorting_states.price", ChannelProductSorting.Price);
|
||||
//});
|
||||
|
||||
//Tab("@channel.tabs.theme", () =>
|
||||
//{
|
||||
// Field(x => x.Theme.ImageId, required: true).Text();
|
||||
//});
|
||||
|
||||
//Tab("@channel.tabs.settings", () =>
|
||||
//{
|
||||
// Field(x => x.ClientNo).Text();
|
||||
// Field(x => x.SortLetter).Text(opts =>
|
||||
// {
|
||||
// opts.Classes.Add("is-short");
|
||||
// opts.MaxLength = 1;
|
||||
// });
|
||||
//});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
using FluentValidation;
|
||||
using Microsoft.AspNetCore.Authentication.Cookies;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
@@ -5,6 +6,10 @@ using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using zero.Commerce.Backoffice;
|
||||
using zero.Commerce.Entities;
|
||||
using zero.Core.Renderer;
|
||||
using zero.Debug.Models;
|
||||
using zero.TestData;
|
||||
using zero.Web;
|
||||
|
||||
@@ -39,6 +44,15 @@ namespace zero.Debug
|
||||
zero.AddPlugin<TestPlugin>();
|
||||
zero.AddPlugin<Commerce.CommercePlugin>();
|
||||
|
||||
zero.WithOptions(opts =>
|
||||
{
|
||||
opts.Extend<IChannel, SalesChannel>();
|
||||
|
||||
//IRenderer<IChannel> renderer = (IRenderer<IChannel>)new SalesChannelRenderer();
|
||||
//renderer.
|
||||
//opts.Renderers.Extend<IChannel, SalesChannelRenderer>();
|
||||
});
|
||||
|
||||
services.AddMvc();
|
||||
|
||||
services.Configure<IISOptions>(opts => opts.AutomaticAuthentication = false);
|
||||
|
||||
@@ -6,6 +6,9 @@
|
||||
</div>
|
||||
|
||||
<aside v-if="index === 0" class="ui-view-box-aside">
|
||||
<ui-property label="@ui.active" :vertical="true" :is-text="true">
|
||||
<ui-toggle v-model="value.isActive" />
|
||||
</ui-property>
|
||||
<ui-property label="@ui.id" :vertical="true" :is-text="true">
|
||||
{{value.id}}
|
||||
</ui-property>
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Newtonsoft.Json;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using zero.Core;
|
||||
using zero.Core.Api;
|
||||
using zero.Core.Entities;
|
||||
using zero.Core.Identity;
|
||||
using zero.Core.Mapper;
|
||||
using zero.Core.Options;
|
||||
using zero.Web.Filters;
|
||||
using zero.Web.Mapper;
|
||||
using zero.Web.Models;
|
||||
|
||||
namespace zero.Web.Controllers
|
||||
@@ -44,6 +42,14 @@ namespace zero.Web.Controllers
|
||||
}
|
||||
|
||||
|
||||
protected JsonResult AsJson(object data)
|
||||
{
|
||||
JsonSerializerSettings settings = JsonConvert.DefaultSettings();
|
||||
settings.TypeNameHandling = TypeNameHandling.Objects;
|
||||
return Json(data, settings);
|
||||
}
|
||||
|
||||
|
||||
protected async Task<IActionResult> As<T, TTarget>(T model) where TTarget : class, new() where T : IZeroEntity
|
||||
{
|
||||
if (model == null)
|
||||
@@ -64,7 +70,7 @@ namespace zero.Web.Controllers
|
||||
//model.CanEdit =
|
||||
}
|
||||
|
||||
return Json(result);
|
||||
return AsJson(result);
|
||||
}
|
||||
|
||||
|
||||
@@ -75,7 +81,7 @@ namespace zero.Web.Controllers
|
||||
return new StatusCodeResult(404);
|
||||
}
|
||||
|
||||
return Json(await Mapper.Map<T, TTarget>(model));
|
||||
return AsJson(await Mapper.Map<T, TTarget>(model));
|
||||
}
|
||||
|
||||
|
||||
@@ -86,7 +92,7 @@ namespace zero.Web.Controllers
|
||||
return new StatusCodeResult(404);
|
||||
}
|
||||
|
||||
return Json(await Mapper.Map<T, TTarget>(model));
|
||||
return AsJson(await Mapper.Map<T, TTarget>(model));
|
||||
}
|
||||
|
||||
protected async Task<IActionResult> As<T, TTarget>(EntityResult<T> model) where TTarget : class, new() where T : IZeroEntity
|
||||
@@ -96,7 +102,7 @@ namespace zero.Web.Controllers
|
||||
return new StatusCodeResult(404);
|
||||
}
|
||||
|
||||
return Json(await Mapper.Map<T, TTarget>(model));
|
||||
return AsJson(await Mapper.Map<T, TTarget>(model));
|
||||
}
|
||||
|
||||
protected async Task<TTarget> Map<T, TTarget>(T model) where TTarget : class, new()
|
||||
|
||||
Reference in New Issue
Block a user