Skip to content

Commit

Permalink
refactor and add unit test for AssetProperties_Item
Browse files Browse the repository at this point in the history
  • Loading branch information
NeVeSpl committed May 12, 2024
1 parent 013981e commit c611dbb
Show file tree
Hide file tree
Showing 19 changed files with 172 additions and 58 deletions.
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
using System.Collections.Generic;
using RevitDBExplorer.Domain.DataModel.ValueContainers.Base;
using RevitExplorer.Visualizations.DrawingVisuals;

// (c) Revit Database Explorer https://github.com/NeVeSpl/RevitDBExplorer/blob/main/license.md

namespace RevitDBExplorer.Domain.DataModel.Accessors
{
internal interface IAccessorWithReadAndSnoop : IAccessor
internal interface IAccessorForDefaultPresenter : IAccessor
{
ReadResult Read(SnoopableContext context, object @object);
IEnumerable<SnoopableObject> Snoop(SnoopableContext context, object @object, IValueContainer state);
IEnumerable<DrawingVisual> GetVisualization(SnoopableContext context, object @object, IValueContainer state);
}
}
29 changes: 24 additions & 5 deletions sources/RevitDBExplorer/Domain/DataModel/Accessors/ReadResult.cs
Original file line number Diff line number Diff line change
@@ -1,22 +1,41 @@
using RevitDBExplorer.Domain.DataModel.ValueContainers.Base;
using System.Diagnostics.CodeAnalysis;
using RevitDBExplorer.Domain.DataModel.ValueContainers.Base;

// (c) Revit Database Explorer https://github.com/NeVeSpl/RevitDBExplorer/blob/main/license.md

namespace RevitDBExplorer.Domain.DataModel.Accessors
{
internal readonly ref struct ReadResult
{
public string Label { get; init; }
public required string Label { get; init; }
public string AccessorName { get; init; }
public bool CanBeSnooped { get; init; }
public required bool CanBeSnooped { get; init; } = false;
public bool CanBeVisualized { get; init; } = false;
public IValueContainer State { get; init; }


public ReadResult(string value, string accessorName, bool canBeSnooped, IValueContainer state = null)
public ReadResult()
{
Label = value;

}


[SetsRequiredMembers]
public ReadResult(string label, string accessorName, bool canBeSnooped, IValueContainer state = null)
{
Label = label;
AccessorName = accessorName;
CanBeSnooped = canBeSnooped;
State = state;
}

[SetsRequiredMembers]
public ReadResult(string label, string accessorName, bool canBeSnooped = false, bool canBeVisualized = false, IValueContainer state = null)
{
Label = label;
AccessorName = accessorName;
CanBeSnooped = canBeSnooped;
CanBeVisualized = canBeVisualized;
State = state;
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,24 +1,29 @@
using System.Collections.Generic;
using System.Linq.Expressions;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Visual;
using RevitDBExplorer.Domain.DataModel.Accessors;
using RevitDBExplorer.Domain.DataModel.ValueContainers.Base;

// (c) Revit Database Explorer https://github.com/NeVeSpl/RevitDBExplorer/blob/main/license.md

namespace RevitDBExplorer.Domain.DataModel.MemberAccessors
{
internal class AssetProperties_Item : MemberAccessorByType<AssetProperties>, ICanCreateMemberAccessor
internal class AssetProperties_Item : MemberAccessorTypedWithDefaultPresenter<AssetProperties>, ICanCreateMemberAccessor
{
IEnumerable<LambdaExpression> ICanCreateMemberAccessor.GetHandledMembers() { yield return (AssetProperties x) => x[0]; }
IEnumerable<LambdaExpression> ICanCreateMemberAccessor.GetHandledMembers() { yield return (AssetProperties x) => x[0]; }


protected override bool CanBeSnoooped(Document document, AssetProperties assetProperties) => assetProperties.Size > 0;
protected override string GetLabel(Document document, AssetProperties assetProperties) => $"[{nameof(AssetProperty)} : {assetProperties.Size}]";
protected override IEnumerable<SnoopableObject> Snooop(Document document, AssetProperties assetProperties)
public override ReadResult Read(SnoopableContext context, AssetProperties assetProperties) => new()
{
Label = Labeler.GetLabelForCollection(nameof(AssetProperty), assetProperties.Size),
CanBeSnooped = assetProperties.Size > 0
};

public override IEnumerable<SnoopableObject> Snoop(SnoopableContext context, AssetProperties assetProperties, IValueContainer state)
{
for (int i = 0; i < assetProperties.Size; i++)
{
yield return new SnoopableObject(document, assetProperties[i]);
yield return new SnoopableObject(context.Document, assetProperties[i]);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

namespace RevitDBExplorer.Domain.DataModel.MemberAccessors
{
internal class MemberAccessorByFunc<TSnoopedObjectType, TReturnType> : MemberAccessorTypedWithReadAndSnoop<TSnoopedObjectType>
internal class MemberAccessorByFunc<TSnoopedObjectType, TReturnType> : MemberAccessorTypedWithDefaultPresenter<TSnoopedObjectType>
{
private readonly Func<Document, TSnoopedObjectType, TReturnType> get;
private readonly Func<Document, TSnoopedObjectType, IEnumerable<SnoopableObject>> snoop;
Expand All @@ -25,7 +25,7 @@ public override ReadResult Read(SnoopableContext context, TSnoopedObjectType @ob
var value = new ValueContainer<TReturnType>();
var result = get(context.Document, @object);
value.SetValueTyped(context, result);
return new ReadResult(value.ValueAsString, "[ByFunc] " + value.TypeHandlerName, value.CanBeSnooped, value);
return new ReadResult(value.ValueAsString, "[ByFunc] " + value.TypeHandlerName, value.CanBeSnooped, value.CanBeVisualized, value);
}
public override IEnumerable<SnoopableObject> Snoop(SnoopableContext context, TSnoopedObjectType @object, IValueContainer state)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

namespace RevitDBExplorer.Domain.DataModel.MemberAccessors
{
internal sealed class MemberAccessorByIteration<TSnoopedObjectType, TReturnType> : MemberAccessorTypedWithReadAndSnoop<TSnoopedObjectType>
internal sealed class MemberAccessorByIteration<TSnoopedObjectType, TReturnType> : MemberAccessorTypedWithDefaultPresenter<TSnoopedObjectType>
{
private readonly string getMethodReturnTypeName;
private readonly ParameterInfo getMethodParameter;
Expand All @@ -30,7 +30,7 @@ public MemberAccessorByIteration(MethodInfo getMethod)
public override ReadResult Read(SnoopableContext context, TSnoopedObjectType @object)
{
var count = CountValues(context, getMethodParameter.ParameterType);
return new ReadResult(Labeler.GetLabelForCollection(getMethodReturnTypeName, count), "[ByIteration]", true);
return new ReadResult(Labeler.GetLabelForCollection(getMethodReturnTypeName, count), "[ByIteration]", true, false);
}
public override IEnumerable<SnoopableObject> Snoop(SnoopableContext context, TSnoopedObjectType @object, IValueContainer state)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

namespace RevitDBExplorer.Domain.DataModel.MemberAccessors
{
internal sealed class MemberAccessorByRef : MemberAccessorTypedWithReadAndSnoop<object>, IAccessorWithCodeGeneration
internal sealed class MemberAccessorByRef : MemberAccessorTypedWithDefaultPresenter<object>, IAccessorWithCodeGeneration
{
private readonly MethodInfo getMethod;

Expand All @@ -28,12 +28,9 @@ public override ReadResult Read(SnoopableContext context, object @object)
var resolvedArgs = ResolveArguments(paramsDef, context.Document, @object);
var result = getMethod.Invoke(@object, resolvedArgs);
value.SetValue(context, result);
return new ReadResult(value.ValueAsString, "[ByRef] " + value.TypeHandlerName, value.CanBeSnooped, value);
}
public override IEnumerable<SnoopableObject> Snoop(SnoopableContext context, object @object, IValueContainer state)
{
return state.Snoop();
return new ReadResult(value.ValueAsString, "[ByRef] " + value.TypeHandlerName, value.CanBeSnooped, value.CanBeVisualized, value);
}


public static Type[] HandledParameterTypes = new[] { typeof(Document), typeof(Options), typeof(View), typeof(SpatialElementBoundaryOptions) };

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

namespace RevitDBExplorer.Domain.DataModel.MemberAccessors
{
internal sealed class MemberAccessorByRefCompiled<TSnoopedObjectType, TReturnType> : MemberAccessorTypedWithReadAndSnoop<TSnoopedObjectType>, IAccessorWithCodeGeneration
internal sealed class MemberAccessorByRefCompiled<TSnoopedObjectType, TReturnType> : MemberAccessorTypedWithDefaultPresenter<TSnoopedObjectType>, IAccessorWithCodeGeneration
{
private readonly MethodInfo getMethod;
private readonly Func<TSnoopedObjectType, TReturnType> func;
Expand All @@ -25,13 +25,8 @@ public override ReadResult Read(SnoopableContext context, TSnoopedObjectType typ
var value = new ValueContainer<TReturnType>();
var result = func(typedObject);
value.SetValueTyped(context, result);
return new ReadResult(value.ValueAsString, "[ByRefComp] " + value.TypeHandlerName, value.CanBeSnooped, value);
}

public override IEnumerable<SnoopableObject> Snoop(SnoopableContext context, TSnoopedObjectType typedObject, IValueContainer state)
{
return state.Snoop();
}
return new ReadResult(value.ValueAsString, "[ByRefComp] " + value.TypeHandlerName, value.CanBeSnooped, value.CanBeVisualized, value);
}


public string GenerateInvocationForScript(TemplateInputsKind inputsKind)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,15 @@

namespace RevitDBExplorer.Domain.DataModel.MemberAccessors
{
internal abstract class MemberAccessorByType<TSnoopedObjectType> : MemberAccessorTypedWithReadAndSnoop<TSnoopedObjectType> where TSnoopedObjectType : class
internal abstract class MemberAccessorByType<TSnoopedObjectType> : MemberAccessorTypedWithDefaultPresenter<TSnoopedObjectType> where TSnoopedObjectType : class
{
public sealed override ReadResult Read(SnoopableContext context, TSnoopedObjectType @object)
{
string label = GetLabel(context.Document, @object);
bool canBeSnooped = CanBeSnoooped(context.Document, @object);
bool canBeVisualized = false;

return new ReadResult(label, "[ByType] " + GetType().GetCSharpName(), canBeSnooped);
return new ReadResult(label, "[ByType] " + GetType().GetCSharpName(), canBeSnooped, canBeVisualized);
}
protected abstract bool CanBeSnoooped(Document document, TSnoopedObjectType value);
protected abstract string GetLabel(Document document, TSnoopedObjectType value);
Expand All @@ -27,4 +28,34 @@ public sealed override IEnumerable<SnoopableObject> Snoop(SnoopableContext conte
}
protected virtual IEnumerable<SnoopableObject> Snooop(Document document, TSnoopedObjectType value) => Enumerable.Empty<SnoopableObject>();
}


internal abstract class MemberAccessorByTypeLambda<TSnoopedObjectType> : MemberAccessorByType<TSnoopedObjectType> where TSnoopedObjectType : class
{
public Overrides Override { get; } = new Overrides();

protected override bool CanBeSnoooped(Document document, TSnoopedObjectType value)
{
ArgumentNullException.ThrowIfNull(Override.CanBeSnooped);
return Override.CanBeSnooped(document, value);
}
protected override string GetLabel(Document document, TSnoopedObjectType value)
{
ArgumentNullException.ThrowIfNull(Override.GetLabel);
return Override.GetLabel(document, value);
}
protected override IEnumerable<SnoopableObject> Snooop(Document document, TSnoopedObjectType value)
{
if (Override.Snoop == null) return null;
return Override.Snoop(document, value);
}


public class Overrides
{
public Func<Document, TSnoopedObjectType, bool> CanBeSnooped { get; set; }
public Func<Document, TSnoopedObjectType, string> GetLabel { get; set; }
public Func<Document, TSnoopedObjectType, IEnumerable<SnoopableObject>> Snoop { get; set; }
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ namespace RevitDBExplorer.Domain.DataModel.MemberAccessors
{
internal static class MemberAccessorFactory
{
private static readonly Dictionary<string, Func<IAccessor>> forTypeMembers = new();
private static readonly Dictionary<string, Func<IAccessor>> memberAccessorOverrides = new();


public static void Init()
Expand All @@ -26,7 +26,7 @@ static MemberAccessorFactory()
foreach (var handledMember in accessor.GetHandledMembers())
{
var memberId = handledMember.GetUniqueId();
forTypeMembers[memberId] = accessor.GetType().CompileFactoryMethod<IAccessor>();
memberAccessorOverrides[memberId] = accessor.GetType().CompileFactoryMethod<IAccessor>();
}
}
}
Expand All @@ -50,20 +50,20 @@ public static IAccessor CreateMemberAccessor(MethodInfo getMethod, MethodInfo se

private static IAccessor CreateMemberAccessor(MethodInfo getMethod)
{
if (memberAccessorOverrides.TryGetValue(getMethod.GetUniqueId(), out Func<IAccessor> factory))
{
return factory();
}

if (getMethod.IsStatic)
{
return new MemberAccessorForStatic(getMethod);
}

if (getMethod.ReturnType == typeof(void) && getMethod.Name != "GetOverridableHookParameters")
if (getMethod.ReturnType == typeof(void))
{
return new MemberAccessorForNotExposed(getMethod);
}

if (forTypeMembers.TryGetValue(getMethod.GetUniqueId(), out Func<IAccessor> factory))
{
return factory();
}
}

var @params = getMethod.GetParameters();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

namespace RevitDBExplorer.Domain.DataModel.MemberAccessors
{
internal sealed class MemberAccessorForConstValue : MemberAccessorTypedWithReadAndSnoop<object>
internal sealed class MemberAccessorForConstValue : MemberAccessorTypedWithDefaultPresenter<object>
{
private readonly IValueContainer value;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using RevitDBExplorer.Domain.DataModel.ValueContainers.Base;
using RevitDBExplorer.Domain.DataModel.ValueViewModels;
using RevitDBExplorer.Domain.DataModel.ValueViewModels.Base;
using RevitExplorer.Visualizations.DrawingVisuals;

// (c) Revit Database Explorer https://github.com/NeVeSpl/RevitDBExplorer/blob/main/license.md

Expand All @@ -24,27 +25,41 @@ IValueViewModel IAccessor.CreatePresenter(SnoopableContext context, object @obje
}


internal abstract class MemberAccessorTypedWithReadAndSnoop<TSnoopedObjectType> : MemberAccessorTyped<TSnoopedObjectType>, IAccessorWithReadAndSnoop
internal abstract class MemberAccessorTypedWithDefaultPresenter<TSnoopedObjectType> : MemberAccessorTyped<TSnoopedObjectType>, IAccessorForDefaultPresenter
{
public override IValueViewModel CreatePresenter(SnoopableContext context, TSnoopedObjectType @object)
{
return new DefaultPresenter(this);
}

ReadResult IAccessorWithReadAndSnoop.Read(SnoopableContext context, object @object)
ReadResult IAccessorForDefaultPresenter.Read(SnoopableContext context, object @object)
{
Guard.IsAssignableToType<TSnoopedObjectType>(@object);
var typedObject = (TSnoopedObjectType) @object;
return Read(context, typedObject);
}
public abstract ReadResult Read(SnoopableContext context, TSnoopedObjectType typedObject);

IEnumerable<SnoopableObject> IAccessorWithReadAndSnoop.Snoop(SnoopableContext context, object @object, IValueContainer state)
IEnumerable<SnoopableObject> IAccessorForDefaultPresenter.Snoop(SnoopableContext context, object @object, IValueContainer state)
{
Guard.IsAssignableToType<TSnoopedObjectType>(@object);
var typedObject = (TSnoopedObjectType) @object;
return Snoop(context, typedObject, state) ?? Enumerable.Empty<SnoopableObject>();
}
public virtual IEnumerable<SnoopableObject> Snoop(SnoopableContext context, TSnoopedObjectType typedObject, IValueContainer state) => null;
public virtual IEnumerable<SnoopableObject> Snoop(SnoopableContext context, TSnoopedObjectType typedObject, IValueContainer state)
{
return state?.Snoop();
}

IEnumerable<DrawingVisual> IAccessorForDefaultPresenter.GetVisualization(SnoopableContext context, object @object, IValueContainer state)
{
Guard.IsAssignableToType<TSnoopedObjectType>(@object);
var typedObject = (TSnoopedObjectType)@object;
return GetVisualization(context, typedObject, state) ?? Enumerable.Empty<DrawingVisual>();
}
public virtual IEnumerable<DrawingVisual> GetVisualization(SnoopableContext context, TSnoopedObjectType typedObject, IValueContainer state)
{
return state?.GetVisualization();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

namespace RevitDBExplorer.Domain.DataModel.MemberTemplates.Accessors
{
internal class BoundingBox_BoundingBoxIntersectsFilter : MemberAccessorTypedWithReadAndSnoop<BoundingBoxXYZ>
internal class BoundingBox_BoundingBoxIntersectsFilter : MemberAccessorTypedWithDefaultPresenter<BoundingBoxXYZ>
{
public override ReadResult Read(SnoopableContext context, BoundingBoxXYZ boundingBox)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

namespace RevitDBExplorer.Domain.DataModel.MemberTemplates.Accessors
{
internal class HostObjectUtils_GetSideFaces : MemberAccessorTypedWithReadAndSnoop<HostObject>
internal class HostObjectUtils_GetSideFaces : MemberAccessorTypedWithDefaultPresenter<HostObject>
{
public override ReadResult Read(SnoopableContext context, HostObject element)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

namespace RevitDBExplorer.Domain.DataModel.MemberTemplates.Accessors
{
internal class JoinGeometryUtils_IsCuttingElementInJoin : MemberAccessorTypedWithReadAndSnoop<Element>
internal class JoinGeometryUtils_IsCuttingElementInJoin : MemberAccessorTypedWithDefaultPresenter<Element>
{
public override ReadResult Read(SnoopableContext context, Element element)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

namespace RevitDBExplorer.Domain.DataModel.MemberTemplates.Accessors
{
internal class Schema_GetAllElements : MemberAccessorTypedWithReadAndSnoop<Schema>
internal class Schema_GetAllElements : MemberAccessorTypedWithDefaultPresenter<Schema>
{
public override ReadResult Read(SnoopableContext context, Schema schema)
{
Expand Down
Loading

0 comments on commit c611dbb

Please sign in to comment.