Skip to content
Permalink
Browse files

ModelMapper: Add helper extensions ModelType, AddControlsNode, AddRep…

…ositoryItemNode, AddViewItemNode, GetRepositoryItemNode etc
  • Loading branch information...
apobekiaris committed Aug 10, 2019
1 parent 4385898 commit de14e5f45647f67660d5694670c0282110644adf
2 go.ps1
@@ -8,7 +8,7 @@ param(
[string]$branch="lab",
[switch]$InstallModules,
[string[]]$taskList=@("Release"),
[string]$XpandPwshVersion = "0.13.3",
[string]$XpandPwshVersion = "0.14.0",
[switch]$Release
)
$ErrorActionPreference = "Stop"
@@ -1,15 +1,9 @@
using System;
using DevExpress.ExpressApp.Model;
using DevExpress.ExpressApp.Model;
using DevExpress.ExpressApp.Model.Core;

namespace Xpand.Source.Extensions.XAF.Model{
internal static partial class ModelExtensions{
public static void ReadFromModel(this IModelNode modelNode,IModelNode readFrom){
modelNode.ReadFromModel( readFrom, null);
}

public static void ReadFromModel(this IModelNode modelNode,
IModelNode readFrom, Func<string, bool> aspectNamePredicate){
var modelApplication = (ModelApplicationBase) readFrom.Application;
for (var i = 0; i < modelApplication.AspectCount; i++){
var aspect = modelApplication.GetAspect(i);
@@ -18,5 +12,6 @@ internal static partial class ModelExtensions{
new ModelXmlReader().ReadFromString(modelNode, aspect, xml);
}
}

}
}
@@ -60,6 +60,16 @@ typeToMap.ModelTypeName();
typeToMap.ModelMapContainerName();
typeToMap.ModelListType();
typeToMap.ModelListItemType();
//GetRepositoryItemNode, AddRepositoryItemNode, GetControlsItemNode, AddControlsItemNode
var listView = (IModelListView)application.Model.Views["Customer_ListView"];
var listViewColumn = listView.Columns["Name"];
listViewColumn.GetRepositoryItemNode(PredefinedMap.RepositoryItemButtonEdit);
listViewColumn.AddRepositoryItemNode(PredefinedMap.RepositoryItem);
var detailView = (IModelDetailView)application.Model.Views["Customer_DetailView"];
var modelPropertyEditor = detailView.Items["Name"];
modelPropertyEditor.GetRepositoryItemNode(PredefinedMap.RepositoryItemButtonEdit);
modelPropertyEditor.AddRepositoryItemNode(PredefinedMap.RepositoryItem);
```

To extend an existing map you can use:
@@ -9,10 +9,12 @@
using DevExpress.ExpressApp.Editors;
using DevExpress.ExpressApp.Layout;
using DevExpress.ExpressApp.Model;
using DevExpress.ExpressApp.Model.Core;
using DevExpress.ExpressApp.SystemModule;
using DevExpress.Persistent.Base;
using Fasterflect;
using Xpand.Source.Extensions.System.AppDomain;
using Xpand.Source.Extensions.XAF.Model;
using Xpand.Source.Extensions.XAF.XafApplication;
using Xpand.XAF.Modules.ModelMapper.Configuration;
using Xpand.XAF.Modules.ModelMapper.Services.Predefined;
@@ -250,9 +252,58 @@ public static class PredefinedMapService{
throw new NotImplementedException(predefinedMap.ToString());
}

public static IModelNode AddControlsNode(this IModelNode modelNode, PredefinedMap predefinedMap,string id = null){
return AddViewItemNode(modelNode, predefinedMap, id, ViewItemService.PropertyEditorControlMapName);
}

public static IModelNode AddRepositoryItemNode(this IModelNode modelNode, PredefinedMap predefinedMap,string id=null){
return AddViewItemNode(modelNode, predefinedMap, id, ViewItemService.RepositoryItemsMapName);
}

private static IModelNode AddViewItemNode(IModelNode modelNode, PredefinedMap predefinedMap, string id,string mapName){
id = id ?? predefinedMap.ToString();
var node = modelNode.GetNode(mapName);
return node.AddNode(predefinedMap.TypeToMap().ModelType(), id);
}


public static IModelNode GetRepositoryItemNode(this IModelNode modelNode, PredefinedMap predefinedMap){
if (!predefinedMap.IsRepositoryItem()){
throw new ArgumentException($"{predefinedMap} is not repository");
}
return ViewItemNode(modelNode, predefinedMap, ViewItemService.RepositoryItemsMapName);
}

public static IModelNode GetControlsItemNode(this IModelNode modelNode, PredefinedMap predefinedMap){
return ViewItemNode(modelNode, predefinedMap, ViewItemService.PropertyEditorControlMapName);
}

private static IModelNode ViewItemNode(IModelNode modelNode, PredefinedMap predefinedMap, string mapName){
if (modelNode is IModelColumn || modelNode is IModelPropertyEditor){
return modelNode.GetNode(mapName).GetNode(predefinedMap);
}

throw new ArgumentException(
$"{nameof(modelNode)} should be ${nameof(IModelColumn)} or {nameof(IModelPropertyEditor)}");
}

public static IModelNode GetNode(this IModelNode modelNode, PredefinedMap predefinedMap){
return modelNode
.GetNode(predefinedMap.TypeToMap().Name);
var modelListType = modelNode.ModelListType();
var typeToMap = predefinedMap.TypeToMap();
if (modelListType != null){
var modelNodes = modelNode.Nodes().Where(node => node.GetType()
.GetInterfaces().Any(type => {
var mapLinkAttribute = type.Attribute<ModelMapLinkAttribute>();
return mapLinkAttribute != null &&Type.GetType(mapLinkAttribute.LinkedTypeName) == typeToMap;
})).Cast<ModelNode>().ToArray();
var modelApplicationBase = ((ModelNode) modelNode).CreatorInstance.CreateModelApplication();
foreach (var node in modelNodes){
modelApplicationBase.ReadFromModel(node);
}
return modelApplicationBase;
}

return modelNode.GetNode(typeToMap.Name);
}

public static object GetViewControl(this PredefinedMap predefinedMap, CompositeView view, string model){
@@ -194,6 +194,10 @@ public static IObservable<Type> MapToModel<TModelMapperConfiguration>(this IObse
return modelNode.GetNode(type.Name);
}

public static Type ModelType(this Type type, Type rootType = null,IModelMapperConfiguration configuration = null){
return DevExpress.ExpressApp.XafTypesInfo.Instance.FindTypeInfo(type.ModelTypeName(rootType, configuration)).Type;
}

public static string ModelTypeName(this Type type,Type rootType=null, IModelMapperConfiguration configuration=null){
if (rootType==null){
rootType = type;
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<ProjectGuid>{F15810E7-4D84-4305-B9DE-74E7976C9018}</ProjectGuid>
<TargetFramework>net461</TargetFramework>
@@ -42,13 +42,15 @@
<Compile Include="..\..\Extensions\Extensions\System\Refelction\PropertyInfoAccessModifier.cs" Link="LinkedFiles\PropertyInfoAccessModifier.cs" />
<Compile Include="..\..\Extensions\Extensions\System\String\CleanCodeName.cs" Link="LinkedFiles\CleanCodeName.cs" />
<Compile Include="..\..\Extensions\Extensions\System\String\ToLiteral.cs" Link="LinkedFiles\ToLiteral.cs" />
<Compile Include="..\..\Extensions\Extensions\XAF\Model\AddNode.cs" Link="LinkedFiles\AddNode.cs" />
<Compile Include="..\..\Extensions\Extensions\XAF\Model\FastModelAccess.cs" Link="LinkedFiles\FastModelAccess.cs" />
<Compile Include="..\..\Extensions\Extensions\XAF\Model\GetParent.cs" Link="LinkedFiles\GetParent.cs" />
<Compile Include="..\..\Extensions\Extensions\XAF\Model\GetValue.cs" Link="LinkedFiles\GetValue.cs" />
<Compile Include="..\..\Extensions\Extensions\XAF\Model\Id.cs" Link="LinkedFiles\Id.cs" />
<Compile Include="..\..\Extensions\Extensions\XAF\Model\ModelListType.cs" Link="LinkedFiles\ModelListType.cs" />
<Compile Include="..\..\Extensions\Extensions\XAF\Model\Nodes.cs" Link="LinkedFiles\Nodes.cs" />
<Compile Include="..\..\Extensions\Extensions\XAF\Model\ObjectViewItems.cs" Link="LinkedFiles\ObjectViewItems.cs" />
<Compile Include="..\..\Extensions\Extensions\XAF\Model\ReadFromModel.cs" Link="LinkedFiles\ReadFromModel.cs" />
<Compile Include="..\..\extensions\extensions\xaf\xafapplication\GetPlatform.cs" Link="LinkedFiles\GetPlatform.cs" />
<Compile Update="Module.cs">
<SubType>Component</SubType>
@@ -1,6 +1,5 @@
using System;
using System.Linq;
using System.Reactive.Concurrency;
using System.Reactive.Linq;
using DevExpress.ExpressApp;
using DevExpress.ExpressApp.DC;
@@ -78,10 +77,8 @@ public static class XafApplicationRXExtensions{
}

public static IObservable<ITypesInfo> WhenCustomizingTypesInfo(this XafApplication application) {
return application.Modules.OfType<ReactiveModule>().ToObservable(Scheduler.Default)
.Repeat()
.FirstAsync()
.Select(_ => _.ModifyTypesInfo).Switch();
return application.Modules.OfType<ReactiveModule>().ToObservable()
.SelectMany(_ => _.SetupCompleted).Cast<ReactiveModule>().SelectMany(_ => _.ModifyTypesInfo);
}

public static IObservable<(XafApplication application, CreateCustomObjectSpaceProviderEventArgs e)> WhenCreateCustomObjectSpaceProvider(this XafApplication application){
@@ -87,8 +87,8 @@ public class CloneModelViewTests : BaseTest{

[Theory]
[InlineData(CloneViewType.LookupListView, Platform.Win)]
[InlineData(CloneViewType.ListView, Platform.Win)]
[InlineData(CloneViewType.LookupListView,Platform.Web)]
[InlineData(CloneViewType.ListView, Platform.Win)]
[InlineData(CloneViewType.ListView,Platform.Web)]
internal void Clone_Model_ListView_and_change_its_detailview(CloneViewType cloneViewType, Platform platform){
var cloneViewId = $"{nameof(Clone_Model_ListView_and_change_its_detailview)}{platform}_";
@@ -102,17 +102,20 @@ public class CloneModelViewTests : BaseTest{
}, platform).Application;
var modelListView = (IModelListView) application.Model.Views[listViewId];
modelListView.DetailView.Id.ShouldBe(detailViewId);
application.Dispose(); }
application.Dispose();
}

private static CloneModelViewModule DefaultCloneModelViewModule(Action<ITypesInfo> customizeTypesInfo,Platform platform){
var application = platform.NewApplication();
application.Modules.Add(new ReactiveModule());
application.WhenCustomizingTypesInfo().FirstAsync(info => {
customizeTypesInfo(info);
return true;
})
.Subscribe();

var cloneModelViewModule = new CloneModelViewModule();

cloneModelViewModule.RequiredModuleTypes.Add(typeof(ReactiveModule));
return (CloneModelViewModule) application.AddModule(cloneModelViewModule,true, typeof(CMV));
}
@@ -54,6 +54,41 @@ public class ModelMapperExtenderServiceTests : ModelMapperBaseTest{
AssertExtendedListViewModel(typeToMap, application, MMListViewNodePath);
}

[Fact]
public void Get_PredefinedModelNode(){
InitializeMapperService($"{nameof(Customize_PredifienedMaps_TargetInterface)}",Platform.Win);

var module = PredefinedMap.GridView.Extend();
var application = DefaultModelMapperModule(Platform.Win,module).Application;

application.Model.Views.OfType<IModelListView>().First().GetNode(PredefinedMap.GridView).ShouldNotBeNull();
}

[Fact]
public void Get_PredefinedViewItemMergedModelNode(){
InitializeMapperService($"{nameof(Customize_PredifienedMaps_TargetInterface)}",Platform.Win);

var module = new[]{PredefinedMap.RepositoryItem,PredefinedMap.RepositoryFieldPicker,PredefinedMap.RepositoryItemBlobBaseEdit}.Extend();
var application = DefaultModelMapperModule(Platform.Win,module).Application;

var modelColumn = application.Model.GetNodeByPath(MMListViewTestItemNodePath);

var repositoryItemModel = modelColumn.AddRepositoryItemNode(PredefinedMap.RepositoryItem);
repositoryItemModel.SetValue("Name","Base");
repositoryItemModel.SetValue("AccessibleName","AccessibleNameBase");
var repositoryFieldPickerModel = modelColumn.AddRepositoryItemNode(PredefinedMap.RepositoryFieldPicker);
repositoryFieldPickerModel.SetValue("Name","Derivved");
repositoryFieldPickerModel.SetValue("AccessibleName","AccessibleName");
var repositoryItemBlobBaseEdit = modelColumn.AddRepositoryItemNode(PredefinedMap.RepositoryItemBlobBaseEdit);
repositoryItemBlobBaseEdit.SetValue("Name","NotMerged");

var finalNode = modelColumn.GetRepositoryItemNode(PredefinedMap.RepositoryFieldPicker);
finalNode.GetValue<string>("Name").ShouldBe("Derivved");
finalNode.GetValue<string>("AccessibleName").ShouldBe("AccessibleName");

modelColumn.GetRepositoryItemNode(PredefinedMap.RepositoryItemBlobBaseEdit).GetValue<string>("Name").ShouldBe("NotMerged");
}

[Fact]
internal void Customize_PredifienedMaps_TargetInterface(){
InitializeMapperService($"{nameof(Customize_PredifienedMaps_TargetInterface)}",Platform.Win);
@@ -244,14 +279,14 @@ public class ModelMapperExtenderServiceTests : ModelMapperBaseTest{
[InlineData(Platform.Web,PredefinedMap.ASPxHyperLink)]
[InlineData(Platform.Win,PredefinedMap.RichEditControl)]
[InlineData(Platform.Win,PredefinedMap.RepositoryItem)]
internal void Extend_Existing_ViewItemMap(Platform platform,PredefinedMap PredefinedMap){
var mapPropertyName=PredefinedMap.IsRepositoryItem()?ViewItemService.RepositoryItemsMapName:ViewItemService.PropertyEditorControlMapName;
internal void Extend_Existing_ViewItemMap(Platform platform,PredefinedMap predefinedMap){
var mapPropertyName=predefinedMap.IsRepositoryItem()?ViewItemService.RepositoryItemsMapName:ViewItemService.PropertyEditorControlMapName;
InitializeMapperService(nameof(Extend_Existing_ViewItemMap),platform);
var module = new []{PredefinedMap}.Extend();
var module = new []{predefinedMap}.Extend();

module.ApplicationModulesManager
.FirstAsync()
.SelectMany(_ => _.manager.ExtendMap(PredefinedMap))
.SelectMany(_ => _.manager.ExtendMap(predefinedMap))
.Subscribe(_ => {
_.extenders.Add(_.targetInterface,typeof(IModelPredefinedMapExtension));
});
@@ -39,7 +39,7 @@ steps:
**\*Tests*.dll
!**\*TestAdapter.dll
!**\obj\**
runInParallel: false
runInParallel: true
diagnosticsEnabled: true
runTestsInIsolation: true
codeCoverageEnabled: true

0 comments on commit de14e5f

Please sign in to comment.
You can’t perform that action at this time.