|
I really hope someone can help me with this, I've looked everywhere.
I have a class that I want to save to a file, and it was working fine using a static method within the actual class:
static public void save(string fileName, CMyClass c)
{
IFormatter formatter = new BinaryFormatter();
Stream stream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None);
formatter.Serialize(stream, c);
stream.Close();
}
However, I want to use this class remotely, but when I call this method, using a transparent proxy, I get an exception when formatter.Serialize runs.
It says "Attempted to call a method declared on type System.Runtime.Remoting.Messaging.IMethodMessage on an object which exposes CMyClass."
I tried writing the save method as non static, and passing the this pointer to Serialize, but I get another error, which doesn't surprize me.
Does anyone know a simple solution for saving my class?
|
|
|
|
|
CMyClass must be remotable, first of all. This means it must derive from MarshalByRefObject or MarshalByValueComponent and be attributed with the SerializableAttribute (optionally implementing ISerializable if you want to explicitly control serialization).
A few things about design, though. First, never prefix classes with "C". There's a naming convention for every framework - like the .NET Framework - for a reason: to provide consistent naming through the framework. Microsoft has done a pretty good job of this throughout the .NET FCL (Framework Class Library) with only a few exceptions. See Naming Guidelines[^] in the .NET Framework SDK for more information.
Also, if an instance of CMyClass is what you're saving, then your method should be an instance method (not static). What you're doing works, but it's not a very good object-oriented design because the instance is what you're saving. Statics are usually reserved for properties, methods, and fields (like constants) that apply to the class, not an instance of the class.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Firstly, thanks for the information about naming conventions for the framework, I guess I'm just stuck in my ways because of many years of coding in C++ and using a C in front of classes.
MyClass does inherit from MarshalByRefObject, and it is attributed with the SerializableAttribute, sorry I missed them.
I do want to use an instance method to save the instance. Like so:
public void save(string fileName){
try
{
IFormatter formatter = new BinaryFormatter();
Stream stream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None);
formatter.Serialize(stream, this);
stream.Close();
}
catch(Exception e){
MessageBox.Show(e.Message);
}
}
Which would be ideal, however when this is run an exception is thrown with the following message:
"The type System.Runtime.Remoting.ServerIdentity in Assembly mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 is not marked as serializable."
Everything stored in MyClass is marked as serializable, it saves fine when using my static method, but not when called remotely. All other remote calls in MyClass work ok.
|
|
|
|
|
10+ years of C/C++, about 5 with Perl, 6 with Java and now about 3 with .NET: each uses a different naming convention. It's just something you have to get used to.
It's not that it wouldn't save when using a static method, just that it's not a very good OO design.
As far as the error goes (which would've been helpful), some member of your class uses the ServerIdentity Type, which isn't serializable. I suggest implementing ISerializable and serializing only those fields you want to save. There's no documentation for this Type so without digging through the IL I couldn't tell you want it does (though the name gives me a few ideas), but chances are that whatever field Type defines such a property is probably something you don't need to save.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Thanks for your help Heath.
Through debugging I found out that ServerIdentity seems to be used by MarshalByRef, so when my code trys to serialize it, it won't allow it. From the .net help files I found this:
"CAUTION As a general design pattern, it would be unusual for a class to be both marked with the serializable attribute and extend MarshalByRefObject. Developers should think carefully about the possible serialization and remoting scenarios when combining these two characteristics..... For more details about serialization of classes that extend MarshalByRefObject see RemotingSurrogateSelector"
There is not a great deal of information about using RemotingSurrogateSelector, on the internet, or the .net help. So I have decided to do it a different way.
The class 'MyClass' is actually called SupremeHome and is the main class in my home automation program I'm writing, it holds collections of various objects. Each object I want to save will now implement ICloneable. SupremeHome will have a (non static) method called Save that will create a new SupremeHome object based on itself, using ICloneable.Clone(), then write the whole thing to disk with the given file name. I have tested it a bit and it works ok.
|
|
|
|
|
A RemotingSurrogateSelector selects surrogates - or class that serialize other classes that aren't serializable themselves. So, if some class isn't marked with the SerializationAttribute (and hence, not serializable regardless of whether or not is extends MarshalByRefObject ), then you add an ISerializationSurrogate implementation associated with a Type you want to serialize.
What you're doing right now - though it may work - is very inefficient. As I mentioned before, you should just implement ISerializable (forget what MSDN says in this case - Microsoft does it throughout the FCL and I use it throughout a very large N-tier application I architected at work that uses .NET Remoting and a heck of a lot of sinks) and not serialize what you don't need to pass to the other application domain.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
I see what you mean about inefficiency, and as implementing ISerializable requires about the same amount of coding, I am now doing it that way. Thanks again for your help.
|
|
|
|
|
According to msdn and all .NET 1.1 docs, the ToolBar.BackColor property is intended to be public. Every attempt to access it in code, however, indicates that it was accidentally implemented as private. I have tried deriving new subclass from ToolBar to override the property and have tried casting up the chain to Control.BackColor. Neither route has worked. Any ideas on how to change the color of a ToolBar?
|
|
|
|
|
It's not provide, but it is hidden from the code editor and property grid using the BrowsableAttribute and the EditorBrowsableAttribute . Why? Because it does nothing. This is actually common throughout the System.Windows.Forms members. You cannot explicitly set the background color of a ToolBar because the Toolbar common control that the ToolBar class encapsulates does not support background colors. It uses the Control color defined in your display settings. The same goes for a background image.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Hello,
I am trying to figure out a solution for hosting an application in IE, but runs on the client machine (to access printer configuration). I want to use C#, b/c the client has the .NET runtime, otherwise the answer would be, develop an ActiveX control (ATL).
Does anyone know how to write a C# app (winform) that is hosted in Internet Explorer?
For example, the user browses to http://someserver/somepage.aspx , which then downloads the C# app, and is hosted in IE. The app then has control to access printers on the local machine and local network (the same way windows does)
Thanks.
R.Bischoff
.NET, Kommst du mit?
|
|
|
|
|
|
Thanks for your helpful information.
How would you access the PrintDialog control from the control you are hosting in IE ?
Thanks.
R.Bischoff
.NET, Kommst du mit?
|
|
|
|
|
Same as you would using any other form. It's just a control. If you're trying to access the print dialog for IE, that's not so simple and involves dispatch interfaces and client-side scripting.
You must also have the right code access permissions, which are documented in the class documentation for the classes you want to use.
My article does discuss code access security a little, so you need to author your control with this in mind. You shouldn't just assume you'll have FullTrust permissions - that's poor design.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
|
Hi, I'm making a game and for some reason can't figure out how to play two sound events at the same time. I have a background playing but while it is playing another event can't seem to play. I know winmm.dll will not do it but i thought quartz.dll will.
here is what i have tried
public QuartzTypeLib.FilgraphManagerClass mc;
public QuartzTypeLib.FilgraphManagerClass froghop;
mc = new QuartzTypeLib.FilgraphManagerClass();
froghop = new QuartzTypeLib.FilgraphManagerClass();
QuartzTypeLib.FilgraphManager graphManager =
new QuartzTypeLib.FilgraphManager();
mc =(QuartzTypeLib.FilgraphManagerClass)graphManager;
froghop =(QuartzTypeLib.FilgraphManagerClass)graphManager;
i then make a thread that has this
mc.RenderFile("whateverbackground.mp3");
mc.Run();
that works fine
but i also have a keydown event that i want to play the froghop
so i try inside the keydown
froghop.RenderFile("blah.mp3");
froghop.Run();
the problem is while the background is playing the froghop never runs. is there away around this? Cause i thought active X's quartz.dll did the trick but i guess not.
Win32newb
"Programming is like sex, make one mistake and you have to support it for a long time"
|
|
|
|
|
First, why are you using MP3s? For long-playing sounds like background music or something, it's fine; but, you need something quick to play, which is why WAVs are pretty common. Just look at the sound events for Windows (although that goes back a long time when WAVs were about the only sound files that existed).
Second, the KeyDown event is fired in the same thread that the control was created in (the UI thread), so if you started your background in the same thread, this may be the cause.
Finally, why not use Managed DirectX 9 instead of inteorp'ing with the ActiveX DLLs? There's a lot better support for managed code and it's not simply interop assemblies - it was written from the ground-up for managed applications. You could use DirectSound for your background sound while playing other sounds asynchronously.
You should try it. Download the Summer 2003 update (it's the full package) from http://msdn.microsoft.com/directx[^].
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Yes, the run method appears to be blocking. I did what you were talking about having one play in the background and the other play async but i was hoping to not have to use two different methods. I'm looking into DirectX now just downloaded the sdk.
What I was currently doing is making the quartzTypeLib play the background which is a mp3
and then i use the tonysound class that i made that uses winmm.dll and i play the wav files seperately. that works just fine. I just did't want to have to include extra code. I figured i could have one library like directx or whatever and then just make new objects of it and play then whenever i want.
Hopefully directx will let me do this.
-tony-
Win32newb
"Programming is like sex, make one mistake and you have to support it for a long time"
|
|
|
|
|
Quartz is part of DirectX - namely DirectShow, IIRC.
You don't need to use separate libraries, just to play the sounds asynchronously.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Ok you keep saying asynch and i know what that is. I just confess i haven't a clue how to do it with quartz.dll I was using winmm.dll before with the async flags but from my understanding and based on what i have seen regardless if i have nowait and nostop flags thrown i still can't play another sound while the primary one is playing. That being with Winmm.dll Also, any idea to why directx sdk refuses to work with VS.net 2002? Do i have to ugrade to 2003 for it to work or something? I tried everything i know of i tried adding the references. i tried putting the dlls in the preassembly folder. nothing works. the wizard wants microsoft.directx.dll and when i add the refernce to the samples
then i get filenotfound exceptions.
Win32newb
"Programming is like sex, make one mistake and you have to support it for a long time"
|
|
|
|
|
I never said anything about async flags - just multi-thread your app and run each sound in a separate thread.
Read my other reply. You didn't install the managed portion of the SDK, which you must do. Works just fine for me. 1) Install the SDK. 2) Install the Managed developer runtime (debug or retail). 3) Write your Managed DirectX application.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Ok trying this DirectX sound with a no go. I installed the sdk. I clicked on the sample file and opened it up. when i go to compile it can't find Microsoft.DirectX or anything in refernece to directX. So I did a search for the dll and added the reference to the project. Now it compiles but i get filenot found exception on the example
Any idea do i need to uninstall directx and reinstall again?
Win32newb
"Programming is like sex, make one mistake and you have to support it for a long time"
|
|
|
|
|
You need to install the Managed DirectX runtime. When you install the SDK, this is not installed. There is a sub-directory of your SDK directory (something like C:\DX90SDK\Developer Runtime\Managed DirectX\Debug) that contains the managed install. This installs the DirectX managed assemblies into the GAC (so they're found at runtime) and adds the install folder to the HKLM\Software\Microsoft\.NETFramework\AssemblyFolders registry key so that VS.NET can find them. Remember, assemblies used during design time don't necessary mean they'll be used at run-time. It's all about how assemblies are resolved.
Take, for example, all the FCL assemblies. While at run-time the assemblies in the GAC are used, at design-time VS.NET (or even the C# compiler, csc.exe with the default response file) use the assemblies in the %WINDIR%\Microsoft.NET\Framework.v<version> directory.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Well thanks for the help but DirectX doesn't want me to learn it evidently.
The samples DO not work. I constantly get the error I describe. I did exactly waht you said I installed the sdk. I then ran the msi to install the managed directx. i then go to vs.net and click on directx wizard and it crashs saying it needs microsoft.directx.dll.
I even try it without the wizard and run the samecode compile and then run, and i get the same exact error. Its obviously a problem cause I have seen it all over the net but i can't seem to find a solution. They basically say the same thing are you but its simply not working for me.
Win32newb
"Programming is like sex, make one mistake and you have to support it for a long time"
|
|
|
|
|
If it's not finding the assembly, then go to the Managed DirectX runtime directory (usually in %WINDIR%\Microsoft.NET\Managed DirectX and run gacutil.exe /i on the assemblies you find in there. This will install them into the GAC so that they can be resolved by the CLR.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Hi Heath,
Here is the start of my webservice Update method. How does this look? Did I leave anything out? Can I use messagebox object inside a webservice? If this is running on the server it wouldn't be viewable to client correct?
<br />
<br />
public bool UpdateDB(dataset dsDiff)<br />
{<br />
string sSQL;<br />
<br />
sSQL = @"SELECT * From MidnightReadings";<br />
<br />
SqlConnection myCon = new SqlConnection("user id=username;" + <br />
"password=password;server=localhost;" + <br />
"Trusted_Connection=yes;" + <br />
"database=database; " + <br />
"connection timeout=30");<br />
<br />
UpdateDB = false;<br />
<br />
try<br />
{<br />
SqlDataAdapter da = new SqlDataAdapter(sSQL,myCon);<br />
SqlCommandBuilder cb = new SqlCommandBuilder(da);<br />
cb.GetInsertCommand();<br />
cb.GetUpdateCommand();<br />
da.Fill(dsDiff,"MidNight");<br />
da.Update(dsDiff);<br />
<br />
}<br />
catch(SqlException e)<br />
{<br />
string errorMessage = "Message: " + e.Message + "\n" +<br />
"Source: " + e.Source + "\n" +<br />
"State: " + e.State + "\n" +<br />
"Procedure: " + e.Procedure + "\n";<br />
<br />
System.Diagnostics.EventLog log = new System.Diagnostics.EventLog();<br />
log.Source = "Web Service: wsMNMhzData Encountered an Error";<br />
log.WriteEntry(errorMessage);<br />
Console.WriteLine("An exception occurred. Please contact your system administrator.");<br />
}<br />
<br />
<br />
<br />
<br />
return true;<br />
}<br />
<br />
Thanks,
JJ
|
|
|
|
|