Plateforme Level Extreme
Abonnement
Profil corporatif
Produits & Services
Support
Légal
English
Problem passing array to .NET COM
Message
Information générale
Forum:
Visual FoxPro
Catégorie:
COM/DCOM et OLE Automation
Versions des environnements
Visual FoxPro:
VFP 9 SP2
OS:
Windows 7
Divers
Thread ID:
01523745
Message ID:
01523995
Vues:
42
>John,
>
>Since you are in control of the .NET code I would highly recommend that you simplify this and add methods that create these objects and add them to an internally managed array. This is way easier than trying to hand code up some XML and then serializing/deserializing.
>
>Create a private property private Contacts[] contacts in your .NET class then create AddContact() and GetContact() (possibly RemoveContact()). You can pass values via parameters or pass in Contact objects which you can easily create via COM.

That's basically what I suggested to Jon in my first reply before he switched to an XML based approach.
I'm not sure I'd dismiss the XML approach without knowing more about the expected usage. If, for example, a couple of hundred contacts were being added then pushing them over the wire one at a time rather than as an array may not be so attractive? Ditto in the opposite direction if a complete list is required on the client side......

What time is it there ?

>Or as I mentioned before with wwDotNetBridge which lets you use arrays (and collections, and generics and a bunch of other stuff that doesn't work with plain COM Interop plus your .NET object doesn't need to be COM registered).
>
>Here's an example of simulated code for your scenario:
>
>
>do wwDotNetBridge
>LOCAL loBridge as wwDotNetBridge
>loBridge = CreateObject("wwDotNetBridge")
>
>*** Load your .NET assembly
>loBridge.LoadAssembly(FULLPATH("ContactManager.dll"))
>
>*** Create the top level .NET object
>loContactManager = loBridge.CreateInstance("MyApp.ContactManager")
>
>*** Create an empty array of MyApp.Contact items 
>loContacts = loBridge.CreateComArray("MyApp.Contact")
>
>*** Create a Contact instance 
>* loContact = loBridge.CreateInstance("MyApp.Contact")
>
>*** Easier way to create a contact object from the array 
>*** since it knows what our base type is
>loContact = loContacts.CreateItem() 
>
>loContact.Name = "Rick"
>loContact.Entered = DATETIME()
>
>*** Add first contact
>loContacts.Add(loContact)
>
>loContact = loContacts.CreateItem() && get a Contact object of type MyApp.Contact
>loContact.Name = "Jim"
>loContact.Entered = DATETIME()
>
>*** Add Second contact
>loContacts.Add(loContact)
>
>*** Call AddContacts(Contacts[] contacts,DateTime enteredOn)
>*** InvokeMethod is required to properly pass the loContact array as a .NET array
>loBridge.InvokeMethod(loContactManager,"AddContacts",loContacts,DATETIME())
>
>*** You can still call most methods direct just like with plain COM Interop
>loContactManager.Close()
>
>
>(note this is off the cuff so there might be minor errors here but it gives you the idea)
>
>Hope this helps,
>
>+++ Rick ---
>
>>Viv,
>>
>>Thank you for the informative response. I tried implementing it but failed when attempting to deserialize. Does the XML output from CURSORTOXML() need to look a certain way for the deserialization to work?
>>
>>Another thing to point out is that I'm only passing over three properties to populate for the Contact object (i.e. first/last name, email), whereas the Contact class has a lot more properties defined. Would the XML need to contain empty elements for the properties I'm not using?
>>
>>Thanks.
>>
>>Jon
>>
>>>Hi,
>>>Sounds OK - but if you don't really need a datatable then if's very simple to use a generic list instead. A couple of generic methods will convert any list of objects to XML and back (assuming the objects themselves are serializable). e.g:
public static class Helper
>>>    {
>>>        public static List<T> RetrieveList<T>(string s)
>>>        {
>>>            XmlSerializer xs = new XmlSerializer(typeof(List<T>));
>>>            System.Xml.XmlReader v = System.Xml.XmlReader.Create(new StringReader(s));
>>>            return (List<T>)xs.Deserialize(v);
>>>        }
>>>
>>>        public static string ConvertToXML<T>(List<T> list)
>>>        {
>>>            XmlSerializer xs = new XmlSerializer(typeof(List<T>));
>>>            StringWriter sw = new StringWriter();
>>>            xs.Serialize(sw, list);
>>>            return sw.ToString();
>>>        }
>>>    }
Example use:
       List<Contact> list = new List<Contact>();
>>>            list.Add(new Contact { Name = "Fred", Age = 33 });
>>>            list.Add(new Contact { Name = "Joe", Age = 66 });
>>>
>>>            string xmlString = Helper.ConvertToXML<Contact>(list);
>>>            //(Examine this string to determine what VFP should create)
>>>
>>>            List<Contact> retrievedList = Helper.RetrieveList<Contact>(xmlString);
>>>>Thanks for the tip. In the meantime, I've decided to switch to sending XML and convert that to a DataTable that I can iterate through. That seems to do the trick for now.
>>>>
>>>>Jon
>>>>
>>>>>>My C# COM DLL has a public method with the following signature:
>>>>>>
>>>>>>public void AddClientsToList(Contact[] contacts, string listName)
>>>>>>
>>>>>>
>>>>>>In VFP, I do the following:
  • Call a DLL method to get a new contact object
  • Populate the properties
  • Create an array and place the object in the first element
  • Call COMARRAY(loDLL,10)

>>>>>>When I attempt loDLL.AddClientsToList(@MyArray, "test"), I get a type mismatch COM error.
>>>>>>
>>>>>>Any ideas on what I'm doing wrong?
>>>>>
>>>>>No. But passing arrays of anything is always a pain. Since you have control of both sides maybe it would be simpler to just pass the Contacts in one-by-one? e.g:
public class MyDll
>>>>>    {
>>>>>        Dictionary<string, List<Contact>> lists = new Dictionary<string, List<Contact>>();
>>>>>        public Contact GetNewContact() { return new Contact();}
>>>>>       
>>>>>        public void AddClientToList(Contact contact,string listName)
>>>>>        {
>>>>>             if (!lists.Keys.Contains(listName))
>>>>>                lists.Add(listName, new List<Contact>());
>>>>>            lists[listName].Add(contact);
>>>>>        }
>>>>>    }
Précédent
Suivant
Répondre
Fil
Voir

Click here to load this message in the networking platform