Page 2 of 2

Re: Importing Notes

PostPosted: Sat Jul 20, 2019 9:39 am
by SBarnes
Hi Ernst,

Although you got this specific example working for the future, for any JiwaCollection, you may want to use the extension method which the following class creates

Code: Select all
public static class JiwaCollectionHelper
{
   public static List<T> ToList<T>( this JiwaFinancials.Jiwa.JiwaApplication.JiwaCollection<T> JiwaColl) where T: JiwaFinancials.Jiwa.JiwaApplication.JiwaCollectionItem<T>
   {
      List<T> result = new List<T>();
      foreach( T item in JiwaColl)
                {
                          result.Add(item);
                }
      return result;
   }
}


to use it it would be something like this

Code: Select all
                JiwaFinancials.Jiwa.JiwaInventory.Inventory inv = (JiwaFinancials.Jiwa.JiwaInventory.Inventory) JiwaBusinessLogic;
      List<JiwaFinancials.Jiwa.JiwaApplication.Notes.Note> notes =  inv.Notes.ToList<JiwaFinancials.Jiwa.JiwaApplication.Notes.Note>();

Re: Importing Notes

PostPosted: Sat Jul 20, 2019 12:27 pm
by pricerc
Of course, the root of this problem is that JiwaCollection<T>.GetEnumerator() returns, not an IEnumerable<T>, but an IEnumerator, which is equivalent to an IEnumerable<Object>; and said objects then need to be wrangled into the correct type when used in a foreach (For Each in VB) loop.

If you're only going to be using the results in a foreach (For Each in VB) loop, and you have no other use for a strongly typed List<T>, then I believe that the following will be more efficient:

Code: Select all
public static IEnumerable<T> ToEnumerable<T>(this JiwaFinancials.Jiwa.JiwaApplication.JiwaCollection<T> JiwaColl) where T: JiwaFinancials.Jiwa.JiwaApplication.JiwaCollectionItem<T>
{
      foreach( T item in JiwaColl)
      {
             yield return item;
      }
}


I haven't tested this yet (although I am now planning to add a VB version to my own shared tools library), but in principle, the yield return will avoid allocating the data structures required for building a List<T>. And if there is more than a slim chance you don't want the whole list (e.g. you're likely to escape the loop before processing every item), then there will be a definite performance benefit to avoiding the List<T>.

Re: Importing Notes

PostPosted: Sat Jul 20, 2019 12:34 pm
by SBarnes
Thanks Ryan

But what I was simply doing was replicating the standard ToList functionality, it would actually be good if the JiwaCollection supported both as built in.

Re: Importing Notes

PostPosted: Sat Jul 20, 2019 2:51 pm
by pricerc
SBarnes wrote:But what I was simply doing was replicating the standard ToList functionality


I know. But I was reading about yield and iterator functions recently, so it was fairly fresh in my mind. I thought this would be a good place to share it, for people who haven't used it before to learn about it, since the conversation includes an example of how it would be useful.

If you're using LINQ (which Mike's original version does), then a function returning IEnumerable<T> will be considerably more efficient than creating a List<T> (which is an implementation of IEnumerable<T>), since FirstOrDefault<T> uses IEnumerable<T> as its input.

That said, replacing the bit of code that was breaking with a bit of code that uses an extension method; instead of:
Code: Select all
     JiwaFinancials.Jiwa.JiwaApplication.Notes.Note existingNote = Inventory.Notes.Cast<JiwaFinancials.Jiwa.JiwaApplication.Notes.Note>().FirstOrDefault(x => noteType != null && x.NoteType.RecID == noteType.RecID);
, it becomes
Code: Select all

JiwaFinancials.Jiwa.JiwaApplication.Notes.Note existingNote = Inventory.Notes.ToEnumerable().FirstOrDefault(x => noteType != null && x.NoteType.RecID == noteType.RecID);


, although, since noteType == null will cause an exception to be thrown before this in the original code, one could just go with:
Code: Select all
var existingNote = Inventory.Notes.ToEnumerable().FirstOrDefault(x => x.NoteType.RecID == noteType.RecID);


And when Jiwa adds IEnumerable(Of T) to JiwaCollection(Of T), then we should be able to do this:
Code: Select all
var existingNote = Inventory.Notes.FirstOrDefault(x => x.NoteType.RecID == noteType.RecID);



SBarnes wrote:it would actually be good if the JiwaCollection supported both as built in.


I'm sure Mike will be reading this :).

Oh, and here's the VB version of the extension method:
Code: Select all
        <Extension()>
        Public Iterator Function ToEnumerable(Of T)(collection As IJiwaCollection(Of T)) As IEnumerable(Of T)
            For Each collectionItem As T In collection
                Yield collectionItem
            Next
        End Function


and an example of wrapping VB.Collection (the underlying collection type in JiwaCollection) to implement IEnumerable(Of T) :)
Code: Select all
    Public Class Foo(Of T)
      Implements IEnumerable(Of T)

      Private _Collection As Microsoft.VisualBasic.Collection

      Public Iterator Function GetEnumerator() As IEnumerator(Of T) Implements IEnumerable(Of T).GetEnumerator
         For Each collectionItem As T In _Collection
            Yield collectionItem
         Next
      End Function
      
      ' required for  IEnumerable(Of T)
      Private Function GetEnumerator1() As IEnumerator Implements IEnumerable.GetEnumerator
         Return Me._Collection.GetEnumerator()
      End Function

      Public ReadOnly Property Collection As Microsoft.VisualBasic.Collection
         Get
            Return Me._Collection
         End Get
      End Property
   End Class

Re: Importing Notes

PostPosted: Sat Jul 20, 2019 4:07 pm
by SBarnes
Hi Ryan,

I've already posted an enhancement request :lol:

Re: Importing Notes

PostPosted: Mon Jul 22, 2019 12:36 pm
by Ernst
OK have just tested this, works Great. SO code posted in Prior Post will work.

Updateds existing Notes, based on Note type. Or Adds new if Note type does not exist.

We use it to update Web KeyWords..:)

Re: Importing Notes

PostPosted: Mon Jul 22, 2019 2:53 pm
by Mike.Sheen
Well, that was all much ado about nothing.

Am I right that the problem Ernst was reporting is that the Cast extension method wasn't recognised?

For that to have happened, someone had to have done something silly like copy and paste the code into a new plugin without realising they needed to import the System.Linq namespace.

Re: Importing Notes

PostPosted: Mon Jul 22, 2019 3:50 pm
by pricerc
Mike.Sheen wrote:Well, that was all much ado about nothing.

Am I right that the problem Ernst was reporting is that the Cast extension method wasn't recognised?

For that to have happened, someone had to have done something silly like copy and paste the code into a new plugin without realising they needed to import the System.Linq namespace.



I did point that out.

And then it went completely off-topic :)

Re: Importing Notes

PostPosted: Mon Jul 22, 2019 3:52 pm
by SBarnes
I test it with the correct statement to include linq and for some reason it wouldn't compile

Re: Importing Notes

PostPosted: Thu Jul 25, 2019 12:28 pm
by Mike.Sheen
SBarnes wrote:I test it with the correct statement to include linq and for some reason it wouldn't compile


Well, I don't know why that would be... I downloaded the last plugin I provided to Ernst in this topic which was for 07.00.175.00, imported it into a 7.2 database and the only two issues was related to the changes needed when adding to the DestinationPropertyCollection on lines 62 and 69.

After making those changes, it compiled fine.

Plugin attached for 7.2.