Closed vigouredelaruse closed 1 year ago
I've looked at your changes, but it's not clear to me what you really want to achieve.
Separating the filter and the action limits the visitor's options. Suppose you want to update something in several places in the tree, then it will be difficult to solve that with 1 filter and 1 action. Then I see more value in 1 action in which the type info of the entity is also given, so that you can create an action in the following way:
var cloneResult = await contentCollectionOperator
.Clone( i =>
i.Include(o => o.AccessControlEntries)
.Include(i => i.HorselessContents)
.Include( i => i.HorselessViews)
.ThenInclude(t => t.Placeholders),
(TypeInfo typeInfo, object entityClone) =>
{
// just an example to filter for multiple types
switch (typeInfo.Name)
{
case nameof(AccessControlEntry):
((AccessControlEntry)entityClone).Name = "Updated AccessControlEntry name";
break;
case nameof(Placeholder):
((Placeholder)entityClone).Title = "Updated Placeholder title";
break;
}
// example to react to global interface type
if (typeof(IContentRowLevelSecured).IsAssignableFrom(type))
{
((IContentRowLevelSecured)entityClone).UpdatedAt = DateTime.UtcNow;
((IContentRowLevelSecured)entityClone).CreatedAt = DateTime.UtcNow;
((IContentRowLevelSecured)entityClone).ObjectId = $"{entityClone.GetType().Name}-{Guid.NewGuid().ToString()}";
}
return entityClone;
},
primaryKey: testContentCollection.Id);
But if you have the same type nested in the graph then it is not possible to make clear which relationship you want to adjust.
But I think that this functionality can also be performed outside the clone functionality. The question is whether this belongs in this library. An external visitor can also arrange this for you. Then it separates the concerns of cloning and adjusting. I am not convinced this should be part of this library.
howdee; thanks for the feedback
Separating the filter and the action limits the visitor's options. agreed - separating the filter and the action adds complexity to the api and can cause the action to duplicate the work of the filter in the worst case of a highly heterogeneous graph.
the situation gets better if the entities are tagged with metadata to differentiate duplicated entity type instances, which is the kind of graph i'm working with at the moment.
as well the implementaters of the filter and the implementers of the action might be on different sides of the security fence. in this scenario the action might be exposed to the final consumer, but the filter may not, which i like a lot
no matter which mechanism i use i don't anticipate being able to express the filter rules and the actions without using code that's tightly coupled to the data structure represented
i think the separate filter shows most benefit if it can be described by an interface, or if the user wants to externalize specification of the rule filters, which is something i'd like to do with the target application
to be as clear as one can be with text diagrams, the workflow i want to enable is the below retrieve template graph -> clone graph -> apply mutations of arbitrary complexity to the graph -> human step -> persist updated graph
if you're still not convinced yet feel free to retire the issue and i will continue to think it through in its various aspects thanks
I think this feature should not be part of this library. The responsibility of this library is just clone a graph of entities by EFC configurations/relationships. Adjusting entities can be done after cloning and before saving.
hello again from utc - 4
i've been experimenting with a delegate api surface that visits each entity in the cloned graph and permits modification of the visited entities
the api surface is exercised by
proposed use case tailor the output of the entitycloner property reset functionality, thus enabling custom operations against the edges of the cloned graph
notes
object DelegateSignature(object param)
which may or may not be desirable, according to the various considerationsi appreciate your consideratoin on the matter thanks