Storing custom classes in CustomDataContainer

Teetow wrote on 11/21/2007, 2:00 PM
I'm trying to store a serialized version of an ArrayList filled with a couple of my custom classes. I've made sure they're all serializable (ints and strings), but I get a "FileNotFoundException" when trying to read it back in. I have no trouble storing a simple string, or even an ArrayList of strings.

What would I have to do in order to store my own classes in the project CustomDataContainer?

Comments

ForumAdmin wrote on 11/26/2007, 7:47 AM
Serialized classes that you store in CustomDataContainers must be defined in compiled assemblies. This is because the assembly name is used in the serialized data. The assembly names that are generated when Vegas runs a script from a source code file are random and not preserved between script runs.

Here is a sample script which works for me when I compile it first and run the dll as a script. It does not work however, when I run the .cs file itself as a script.


using System;
using System.IO;
using System.Collections;
using System.Diagnostics;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;

using System.Windows.Forms;

using Sony.Vegas;

public class EntryPoint {
protected Vegas myVegas;

public void FromVegas(Vegas vegas) {
myVegas = vegas;
InitTestMetadata();

TestSaveProjectMetadata();
TestSaveTrackMetadata();
TestSaveEventMetadata();
TestSaveMediaMetadata();

TestReadProjectMetadata();
TestReadTrackMetadata();
TestReadEventMetadata();
TestReadMediaMetadata();

MessageBox.Show("Success!");
}

[Serializable]
class TestMetaobj
{
public Int32 TestInt;
public Double TestDouble;
public String TestString;

public TestMetaobj(int ti, double td, string ts)
{
TestInt = ti;
TestDouble = td;
TestString = ts;
}

public override String ToString()
{
return String.Format("TestMetaobj: {0}, {1}, {2}", TestInt, TestDouble, TestString);
}
}

Guid testGuid1 = new Guid("1B383239-B996-457a-859F-A37E320BD6A7");
Guid testGuid2 = new Guid("C1B5B22B-E20B-4d00-929A-3AA733193E76");

Byte[] testData = new Byte[256];

void InitTestMetadata()
{
for (int i = 0; i < testData.Length; i++)
{
testData[i] = (byte) i;
}
}

void CompareTestMetadata(Byte[] storedData)
{
Debug.Assert(null != storedData, "stored data not found.");
Debug.Assert(storedData.Length == testData.Length, "bad data length: " + storedData.Length.ToString());
for (int i = 0; i < testData.Length; i++)
{
Debug.Assert(testData[i] == storedData[i], "bad data value.");
}
}

void CompareTestMetaobj(Object storedObj)
{
Debug.Assert(null != storedObj, "stored data not found.");
TestMetaobj obj = (TestMetaobj) storedObj;
Debug.Assert(obj.TestInt == 1234, "bad test int.");
Debug.Assert(obj.TestDouble == 0.9876, "bad test double.");
Debug.Assert(obj.TestString == "this is a test object", "bad test string.");
}

void TestSaveProjectMetadata()
{
TestSaveMetadata(myVegas.Project.CustomData);
}

void TestReadProjectMetadata()
{
TestReadMetadata(myVegas.Project.CustomData);
}

void TestSaveTrackMetadata()
{
foreach (Track track in myVegas.Project.Tracks)
{
TestSaveMetadata(track.CustomData);
}
}

void TestReadTrackMetadata()
{
foreach (Track track in myVegas.Project.Tracks)
{
TestReadMetadata(track.CustomData);
}
}

void TestSaveEventMetadata()
{
foreach (Track track in myVegas.Project.Tracks)
{
foreach (TrackEvent evnt in track.Events)
{
TestSaveMetadata(evnt.CustomData);
}
}
}

void TestReadEventMetadata()
{
foreach (Track track in myVegas.Project.Tracks)
{
foreach (TrackEvent evnt in track.Events)
{
TestReadMetadata(evnt.CustomData);
}
}
}

void TestSaveMediaMetadata()
{
foreach (Media media in myVegas.Project.MediaPool)
{
TestSaveMetadata(media.CustomData);
}
}

void TestReadMediaMetadata()
{
foreach (Media media in myVegas.Project.MediaPool)
{
TestReadMetadata(media.CustomData);
}
}

void TestSaveMetadata(CustomDataContainer customData)
{
customData.SetBytes(testGuid1, testData);
customData.SetObject(testGuid2, new TestMetaobj(1234, 0.9876, "this is a test object"));
}

void TestReadMetadata(CustomDataContainer customData)
{
CompareTestMetadata(customData.GetBytes(testGuid1));
CompareTestMetaobj(customData.GetObject(testGuid2));
}

}
Teetow wrote on 11/27/2007, 11:00 AM
Hmm... I do compile my scripts into assemblies already, so that should have worked... But it's nevertheless great to have some verified sample code to work from. I'll get back if your code fails, then it must be something with how my system is set up.

I never bothered to learn about the .config XML-file and its capabilities, since my stuff has always worked without it. Could that be the culprit? Do I need some method to tell Vegas explicitly where to look for my assemblies?
ForumAdmin wrote on 11/27/2007, 11:24 AM
The script config file would be needed if Vegas can't find an assembly referenced by your script. In the example above, it should not be needed since the assembly that defines the serialized object is the script assembly itself.
Teetow wrote on 11/27/2007, 1:05 PM
OK... In my code, the classes and methods involved are spread over several assemblies. Some is in the baselib, some in the project in question. They all seem to be visible to Vegas, though, since I can run my scripts...

Anyway, I'll get back. Thanks so far =)
Cheesehole wrote on 8/18/2008, 4:23 AM
I'm getting an error when I try to store and then read an object back in:
"Unable to find assembly 'RenderWorm2' "

RenderWorm2 is the name of the application (RenderWorm2.dll) so it is looking for itself?

I tried adding a reference to my dll in a config file but I guess Application Extentions don't read the config files?

I'm just using Int32's and Strings in the object that I'm trying to store and retrieve so I don't know why it is having trouble deserializing the object.

Here is code I'm running:

using (UndoBlock undo = new UndoBlock("RenderWorm Store Settings"))
{
rVegas.Project.CustomData.SetObject(myGuid, myMasterSettings);
}

if (myVegas.Project.CustomData.GetObject(myGuid) != null) System.Windows.MessageBox.Show("Found Data");

And the error:
System.Runtime.Serialization.SerializationException: Unable to find assembly 'RenderWorm2, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.

Thanks!

Ben
Cheesehole wrote on 8/18/2008, 5:18 AM
btw - if I copy my dll to the Vegas folder, it works! I guess this is when I have to figure out this GAC thing?
Cheesehole wrote on 8/18/2008, 8:51 AM
Does anyone know if the GAC stores a copy of the dll or a reference to the dll? For development purposes this could be a problem because if I'm constantly updating the dll the cached version would be different...? For now I just added a post-compile command to the Visual studio project that copies the DLL from the destination folder to the Vegas application folder. So every time I compile it copies the new version of the dll...
Bob Denny wrote on 8/19/2008, 8:19 PM
This whole GAC vs Reference thing is a real mess, and poorly(!) documented/explained by MS. I'm not in a position to explain in detail.

Don't use the GAC unless your assembly (DLL) is used by more than one app. Since it is only used by Vegas, you are doing the right thing by copying it to the Vegas folder.
Cheesehole wrote on 8/20/2008, 4:14 AM
When I make the install package for redistribution, do you think I should
1) install the dll to the GAC
2) install a copy of the dll to the Vegas folder or Windows System (which would put 2x dll's on the users system)
3) or is there a way to install the dll to the Vegas folder and use that as an extension so there would be only 1x copy of my dll?
or
4) is there a way to make Vegas reference the assembly in some other way... it would seem the config files were supposed to provide this function but I don't understand why they don't apply to "extensions"...

Very confusing indeed! I was really happy to see the capability of attaching data to the Vegas project - it's perfect for my application which turns Vegas into a WBT generator. I can save WBT related settings with the VEG file now. But getting it to work has taken longer than coding most of the interface! :-/

Thanks!
Ben