-
-
Notifications
You must be signed in to change notification settings - Fork 361
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Using Spring4D Collections in ViewData #689
Comments
Let dmvcframework depends from Spring4d would be a huge change and huge dependency. We've to find a different approach. |
Probably we could avoid the Spring4D dependency if we can take a Duck Typing approach. I.e. Support Lists by looking for some iteration interface, and Objects by scanning the properties. |
The unit |
I'll add it to my todo list, to investigate. |
I've got some code in my toolbox that is a container that can handle both TObject derived instances as well as reference counted IInterface derived instances. As an aside, I've been using it to implement a class helper for TWebContext (so I can can have application specific pseudo properties anywhere the WebContext is available) by binding it to the CustomIntfObject property. The interface for this container is below - note that it automatically increments and decrements the reference count for IInterface instances to prevent them going out of scope and thus keeps the auto memory management working correctly.
I could probably refactor this to be more general so it would then be suitable as the container for the ViewData, although as implemented it assumes ownership of the contained objects and will call their destructor as part of its owner destructor (this could be changed though). |
The other way is to add an additional ViewData2 container that is generalised for reference counted instances and change the rendering code to iterate over both containers. |
Either way will require a change to the TMVCBaseViewEngine class as this takes the AViewModel (type TMVCViewDataObject) in the constructor. |
OK, so my first naive implementation just stands up a parallel ViewModel that has a TDictionary<string, IInterface> as the storage, and the Mustache renderer takes this as an additional param which it iterates over when preparing the models.
This renders out a Spring4D list with no references to that framework apart from in my controller unit. So we are not coupling DMVC with Spring4D ! I would prefer to propose some changes that preserve the existing interface by modifying the underlying storage so look forward to your feedback when you have time to review. |
Hmm, I wonder if I'm over complicating this LOL.
My next task will be looking at the MVCFramework.DataSet.Utils unit so I can write some code to output the TDataset as a Spring4D IList<T> instance. Modifying the TDataSetUtils.DataSetToObjectList<T> method to accept a duck typed list would enable standard Delphi lists as well as other lists that exhibit list like behaviour (specifically the ability to Add an object) to be used. |
I've found that the TDataSetUtils class has been declared as sealed so this is making it hard to subclass for use with an interfaced list. I might just clone the unit, unless there is a better idea. |
If there is a good reason we can remove the sealed clause. |
Sorry, that was me posting from a work account. I'll take a look and see what duck type list changes would make it work with different lists. |
I'm stuck between trying to add "generic" interfaced list functionality - I've looked at IMVCList (used by TDuckTypedList) but this does not support the IMVCList<T> generic functionality. Or just run with a copy of the unit and rewrite to support Spring4D (so outside of a contribution) to this excellent library. Option 1 is preferable from a community perspective, option 2 from a get-the-job-done perspective. |
I know the feeling. Writing a framework is not like just "make it work" job. |
Option 2 yields the following - unfortunately due to the lack of a generic version of TDuckTyped list I've need to replicate the DataSetToObjectList on the utility class. It also means I have pulled in reference to the Spring collections rather than being able to use TDuckTypedList.IsWrappedList to decide if the list can be wrapped so the Add method can be accessed.
|
Did you tried to just hard-cast the interface reference to Example: uses
MVCFramework.DuckTyping;
{ snip snip snip }
function TWebSiteController.PeopleList: String;
var
LDAL: IPeopleDAL;
lPeople: TPeople;
lPeople2: IInterface;
begin
LDAL := TServicesFactory.GetPeopleDAL;
lPeople := LDAL.GetPeople;
try
lPeople2 := WrapAsList(LDAL.GetPeople); //just for test, lPeople2 is now an interface
ViewData['people'] := lPeople;
ViewData['people2'] := TObject(lPeople2); //having already an interface this should be enough
Result := GetRenderedView(['header', 'people_list', 'footer']);
finally
lPeople.Free;
end;
end; |
ef6edd5 should already solve this issue - the only thing is that you cannot directly assign any interface to TValue but need to write ViewData['...'] := TValue.From(someInterface); |
It looks like there have been some major changes prior to the referenced commit, in particular line 236 of the MVCFramework.View.Renderers.Mustache unit cannot be compiled
Is this part of a released branch or still in the development branch ? |
Did you tested this issue in 3.4.2-magnesium-rc1 ? |
I'm looking at the Spring4D collection classes, in particular the various Lists.
I currently have code in my controllers that fetches a list of objects and adds them to the page to be rendered. However the controller method needs to manage the memory of the list.
If the ViewData would accept an interfaced object, then my code would be simplified removing much of the temporary variable declaration and memory management scaffolding.
The current implementation is looking for a TObject. Can we override it to also accept IInterface and descendants ?
The text was updated successfully, but these errors were encountered: