Using IDataObject

I want to use IDataObject to pass data across a COM interface.  How do I do this.  My COM server is an in-process activeX server with an interface decended from IDispatch using the type library editor.

BigMadDrongo
BigMadDrongoAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

d003303Commented:
Yo,
where do you want the data to go today ;-) The IDataObject interface is quite open, so you may have to supply a LOt of different data formats in that object. If you want to exchange data only between COM objects written by yourself you could declare your own format, but I think you will not use IDataObject then.
I guess you want to use IDataObject to communicate with the shell. Do you want to READ data from IDataObject or WRITE data through a IDataObject ?

Slash/d003303
0
BigMadDrongoAuthor Commented:
What we have is two COM in-process servers which need to share a large amount of data.  This data is stored in a class derived from TComponent, which contains various standard data types and a collection.  Each item in the collection contains various standard data types as well as 3 other collections.  Because there are collections of collections, I can't stream the data into a memory stream and copy that memory stream across the interface  as a variant array because only the first level of collections is stored in the stream using the WriteComponent method.  IDataObject has been recomended to me as a means of sharing this data, but I have no idea how to use it.  I tried to comprehend Kraig Brockschmidt's Understanding Ole, but couldn't, having no knowledge of C++.  If you know hoe to use it, any help will be appreciated, or if you can suggest an alternative method, then I'm all ears.

Cheers

BigMadDrongo
0
d003303Commented:
OK,
it does not matter what interface you use. IDataObject is a standard interface to the OLE world. But very complex to use.
So your goal is to stream private data over a COM interface between private COM objects. So we should first focus on the data itself.
It will be best to use the internal streaming system of Delphi. Let's take a look at your object structure :

MyComponent
-MyProperty1
-MyProperty2
-MyCollection1
 -MyCollectionItem1.1
  -MyCollection2
   -MyCollectionItem2.1
   -MyCollectionItem2.2
 -MyCollectionItem1.2
  -MyCollection2
   -MyCollectionItem2.1
   -MyCollectionItem2.2
 -MyCollectionItem1.3
  -MyCollection2
   -MyCollectionItem2.1
   -MyCollectionItem2.2

Most important is that all collections get saved. That is the main thing, not the interface it is streamed over.
To get all your data saved, you will have to override the DefineProperties method of MyCollection1 that each collection item can stream its containing collections. You will need to design a read and write method for the first level of the collections. I'll take a look how to do this in detail.
Again, the interface is not important. If you can use a stream to get your data saved and read again, you've got it !

Slash/d003303
0
Cloud Class® Course: SQL Server Core 2016

This course will introduce you to SQL Server Core 2016, as well as teach you about SSMS, data tools, installation, server configuration, using Management Studio, and writing and executing queries.

BigMadDrongoAuthor Commented:
Where might I find the basic structure for the define properties method?  What code will I need to put in it when I override it.  Unfortunately I've taught myself Delphi from books and although I have overridden some simple functions, I wouldn't know where to start with overriding Define Properties.  Any guidance would be greatly appreciated!

BigMadDrongo
0
d003303Commented:
Yo,
the DefineProperties method defines how your component stores its data. The method

procedure MyComponent.DefineProperties(Filer: TFiler);
begin
  Filer.DefineBinaryProperty('AProperty', ReadAProperty, WriteAProperty, ShallWeWrite);
end;

would notify the Filer object that it should use the ReadAProperty and WriteAProperty to read/write the AProperty property in binary and checks with the ShallWeWrite method if the property shall be written or not. Check the online help on the DefineBinaryProperty and DefineProperty methods.
If you were using only components and not collections, everything would be saved automatically, because every component writes its contained components. So you must close this gap that your collection will write all collections of the containing collection items.
More clearer or more confused now ? I'll give a small example later on.

Slash/d003303
0
BigMadDrongoAuthor Commented:
It's a bit clearer now.  I take it I need to define ReadAProperty and WriteAProperty as procedures which store components into a stream, and the components are of the type passed in as the 'AProperty' string.  How do I go about writing these procedures?  I've looked up TStreamProc in the help files and in the Delphi source, but with no luck.  If you have an example, it would be appreciated.

BigMadDrongo
0
d003303Commented:
OK, i'll prepare an example.

Slash/d003303
0
BigMadDrongoAuthor Commented:
Slash/d003303

Thanks very much.  If it is easier, you can contact me by e-mail on

James_R_Bennett@SBPHRD.COM

Cheers

BigMadDrongo
0
BigMadDrongoAuthor Commented:
I found some info in the Delphi Developers Handbook about the define properties method, and I think I have the hang of it.  What I do is the following:

procedure TRxnScheme.DefineProperties(Filer: TFiler);
begin
  Filer.DefineProperty('fNumberOfCompounds', ReadCompounds, WriteCompounds, True);
  Filer.DefineProperty('fNumberOfAssociations', ReadAssociations, WriteAssociations, True);
end;

procedure TRxnScheme.ReadCompounds(Reader: TReader);
begin
  fNumberOfCompounds := Reader.ReadInteger;
end;

procedure TRxnScheme.WriteCompounds(Writer: TWriter);
begin
  Writer.WriteInteger(fNumberOfCompounds);
end;

procedure TRxnScheme.ReadAssociations(Reader: TReader);
begin
  fNumberOfAssociations := Reader.ReadInteger;
end;

I can stream this into a file, and it stores the relevant bits.  One problem I do have is that some of my properties are variants and enumerated types, and there are no methods in TReader or TWriter to read and write these two types.  How do I read/write them?

Cheers

BigMadDrongo
0
d003303Commented:
Yo,
you will have to write an algorithm that covers the reading/writing process. So e.g. the first thing to save in a variant is the variant type, then depenging on the type its content. Reading is the same thing vice-versa. Enumerations can be saved/read as a set.

Slash/d003303
0
BigMadDrongoAuthor Commented:
Slash/d003303

I've managed to get it all working, streaming to a file and back quite successfully.  If you want the points for your help, just post an answer, and they're yours!

Cheers for your help.

BigMadDrongo
0
d003303Commented:
Yo BigMadDrongo,
nice that it all works !

Slash/d003303
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
BigMadDrongoAuthor Commented:
Cheers for all your help!

BigMadDrongo
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Delphi

From novice to tech pro — start learning today.