constraints and inheritence

Mar 30, 2008 at 3:29 AM
1) My understanding is that I cannot pass a System.IO.Stream directly, because it isn't sealed (even though it is in mscorlib.dll and is Serializable). This makes sense to me, because derived classes (like System.IO.FileStream) aren't serializable and would fail when passed as System.IO.Streams through the pipline. Can I work around this by creating a "CustomFileStream" class though, that derives from System.IO.Stream and internally wraps a FileStream, and then pass it using an IContract? I'd really like to pass my "Decoder" add-ins a filestream that they can read asynchronously. Or does this not work because my CustomFileStream would need to be Serializable as well?

I would think that I CAN do this, but I'm really not sure how inheritence plays in with constraints. Can anyone clarify for me?
Mar 31, 2008 at 7:46 PM
It's seems like you've come up with the perfect real world example to demonstrate why we give that that guideline.

If you wanted to pass your CustomFileStream you would have to figure out a way to make it serializable which will be difficult since it is holding onto a FileStream that is not serializable.

There are two real options you have here:

1. Reconstruct the FileStream across the boundary
If you simply need to give the add-in access to a file you can pass across the path to the file and then convert that to a FileStream in the adapter and then pass that file stream to the add-in. If you need to move it to a particular spot before you hand it over you could also pass your adapter enough information to get there. If this works for you then this is probably is the best way to go as it will give you semantics very close to what it sounds like you are looking for. The downside is that if you need to pass this file stream back across to the host again it will be difficult to accomplish and ensure that it is in the same state the add-in left it in.

2. Create a contract for the necessary pieces of the file stream and marshal by reference
If you need the host and add-in to work on the same filestream and have the changes to the stream on one side impact the other then what you really need is to pass this by reference (through a contract) rather than by value (using serialization or reconstruction). In this case you will need to define the contract with the methods you expect the add-in to need. You would build something like "ICustomFileStreamContract" and have the corresponding pipeline, and then in your host you would implement the host view version of that (CustomFileStream) which holds the actual reference to the filestream object. This is pretty close to the solution you describe above, but my guess is that solution one (passing the file path across and then building the FileStream on the other side) makes more sense for you.

Does that help?

Mar 31, 2008 at 8:07 PM
Edited Mar 31, 2008 at 11:44 PM
My understanding is that #1 would be more efficient, so #1 it is.

Just to clarify though, would #2 work even if CustomFileStream extends System.IO.Stream? or would it only work if it was not derived from anything. The reason i ask, is that if for some reason i opt for #2, the add-ins will want to use binaryreaders on my wrapper class and that won't work unless it actually implements System.IO.Stream (rather than just providing a few read methods that wrap the internal FileStream).

edit: thanks for your helpful assistence, by the way.
Apr 2, 2008 at 5:21 AM
#1 will be MUCH more efficient if it meets your needs.

For #2, you could have the type in the add-in view CustomFileStream extend IO.Stream or you could even use System.IO.Stream as the add-in view for this type. Your ViewToContractAddInAdapter would implement System.IO.Stream and then call across your custom contract to implement whichever parts of System.IO.Stream you wanted to.