|
In C++, I can do this (this is ugly and simplified):
void Foo()
{
CMyClass cMyClass;
Bar( (void*) &cMyClass );
}
void Bar( void* pData )
{
CMyClass* pMyClass = static_cast<CMyClass*>(pData);
}
In C#, how can I convert an object (class) to an array of bytes, send that to someone else (e.g., with sockets), and then recreate that object with that array of bytes. Is using BinaryFormatter on a MemoryStream what I need?
To further complicate things, what if I don't know the class type, but I KNOW that it is derived from a particular base class? E.g., I know it's a CAnimal, but I don't know if it is a CElephant or a CDog. How can I find out?
Thanks
|
|
|
|
|
public void Foo()
{
MyClass o = new MyClass();
Bar(o);
}
public void Bar(object data)
{
MyClass o = (MyClass)data;
} In .NET, everything deriving from Object (except for ValueType and its derivatives like the intrinsics, enums, and structs) are reference types already (well, the instances of the classes deriving from Object ) and everything derives from Object . So, for anything declared as a class , it's instance is a reference type.
As far as sending objects to another context, .NET Remoting is the de facto technology in .NET to do this. In the base class library, you can choose from the BinaryFormatter or the SoapFormatter (binary would obviously be faster but not easily interoperable with other technologies like J2EE). Serialization is required when crossing different contexts (even within the same AppDomain ) and Remoting is recommend (required in some cases) when crossing AppDomain s (even within the same process, which it's recommended you use a TcpChannel for communication). See Accessing Objects in Other Application Domains[^] on MSDN for more information.
For a good intro and intermediate book on .NET Remoting, see "Microsoft .NET Remoting"[^] by McLean, Naftel, and Williams.
As far as dealing with base classes, this is easily handled by an object-oriented framework like .NET and Java. For example, you could declare a parameter as even an Object , or the base class for your objects. The Common Type System (CTS) will ensure that when you're compiling any direct calls to that method use a parameter that is indeed a derivative class of the parameter Type. If you use abstract and virtual methods in your base class and override those in your derivative classes, those methods will be called instead of their base class's methods (you can use the base keyword to call the base class's methods inside the overridden methods). This is polymorphism. See the Common Type System[^] for some more information.
For example, the Object class has a virtual ToString method that, by default, returns the object's Type. If a class overrides this, it can return something else. An Enum returns the enum member name (or a comma-delimited list of names for enums that are attributed with the FlagsAttribute ). Many other classes override this method as well.
Also, the Object.GetType method is not virtual and will return the actual Type of the object, regardless of whether the variable is declared as an object or another base class:
object o = new Button();
Console.WriteLine(o.GetType()); Would print:
System.Windows.Forms.Button So, you can use the GetType to see if you're dealing with an Elephant or a Dog (BTW, the hungarian notation is not recommended for use in .NET languages - just thing of what the base class library uses for examples of how to name your classes, etc., or see the Naming Guidelines[^]).
The C# language makes this easier with several keywords you can use, such as is and as :
public void Feed(Animal a)
{
if (a is Elephant) Buy(Food.Peanuts);
if (a is Dog) Buy(Food.Peanuts);
} Of course, the above example is better suited for polymorphism by using the abstract keyword and overriding in the derivate classes to feed the animal what's necessary, but it's just an example.
-----BEGIN GEEK CODE BLOCK-----
Version: 3.21
GCS/G/MU d- s: a- C++++ UL@ P++(+++) L+(--) E--- W+++ N++ o+ K? w++++ O- M(+) V? PS-- PE Y++ PGP++ t++@ 5 X+++ R+@ tv+ b(-)>b++ DI++++ D+ G e++>+++ h---* r+++ y+++
-----END GEEK CODE BLOCK-----
|
|
|
|
|
Thanks, that helps a lot. I understand polymorphism, I just wasn't sure about how to achieve this in C# syntax.
|
|
|
|
|
Good! I hope I didn't offend you talking about polymorphism. I just usually make assumptions if nothing is indicated in a post to avoid constant reposting to provide more information. If nothing else, someone googling for answers may find our little thread useful (which is why I dislike forum members taking questions directly to me via email - it doesn't benefit the community).
-----BEGIN GEEK CODE BLOCK-----
Version: 3.21
GCS/G/MU d- s: a- C++++ UL@ P++(+++) L+(--) E--- W+++ N++ o+ K? w++++ O- M(+) V? PS-- PE Y++ PGP++ t++@ 5 X+++ R+@ tv+ b(-)>b++ DI++++ D+ G e++>+++ h---* r+++ y+++
-----END GEEK CODE BLOCK-----
|
|
|
|
|
Heath Stewart wrote:
Good! I hope I didn't offend you talking about polymorphism.
None taken. I appreciate your quick and detailed answer.
|
|
|
|
|
hello!
for a testproject I have to load an assembly from a path different to the execution path of my application. the assembly I want to load references other assemblies, which are not system assemblies or assemblies referenced by my application.
the way I load this assembly is easy and works:
Assembly MyAssembly=System.Reflection.Assembly.Load(AssemblyPathandName);
when I enumerate the members of a class of this assembly and the member (for example a method) has a returntype which is declared in a referenced (but not yet loaded) assembly, my application crashs.
now my question:
how can I load the referenced assemblies or how can I change the searchpath of my application, so that the referenced assemblies can be found and loaded automatic??????
|
|
|
|
|
There are a few ways that assemblies are found. First, the CLR will read from <runtime> section of the .config file and see if you've configured any paths for bound assemblies. The application will then use assemblies in the Global Assembly Cache (GAC), starting with native (pre-JIT'd) assemblies first, then the other assemblies (those not pre-JIT'd). Assemblies are then used out of the application directory (the directory where you .exe executable is located), followed by any additional subdirectories configured in the <probing> section of you .config file.
See http://msdn.microsoft.com/library/en-us/cpguide/html/cpconhowruntimelocatesassemblies.asp[^] for more detailed information.
You can also handle the AppDomain.AssemblyResolve event and specify from where the assembly should be loaded (for example, from a different path, across the Internet/an intranet, or even from some Stream ), but it's typically better and easier to maintain to work with the CLR and and let Fusion (the assembly binder) do its job.
-----BEGIN GEEK CODE BLOCK-----
Version: 3.21
GCS/G/MU d- s: a- C++++ UL@ P++(+++) L+(--) E--- W+++ N++ o+ K? w++++ O- M(+) V? PS-- PE Y++ PGP++ t++@ 5 X+++ R+@ tv+ b(-)>b++ DI++++ D+ G e++>+++ h---* r+++ y+++
-----END GEEK CODE BLOCK-----
|
|
|
|
|
We have an assembly that is in the GAC, but it’s a .NET component that is used inside visual studio itself. Ie it’s a .NET assembly control you drag onto a windows form application. I am trying to install the assembly on a remote machine (installshield devstuio 9) and get it to show up as a reference automatically in vstudio2003. How can I automatically add a reference to Visual studio in an installer / registry hack / command line that links to an assembly in the GAC? Without having to browse for it from the GAC.
Thanks
paul@lightbulb.co.uk
|
|
|
|
|
For some weird reason, VS.NET doesn't see assemblies in the GAC. You have to add a registry key under HKEY_LOCAL_MACHINE\Software\Microsoft\.NETFramework\AssemblyFolders (see the existing ones for examples). Add the path to the assemblies outside the GAC, though it would be good to add the assemblies to the GAC, too, since it bolsters versioning and - if you ngen then (pre-JIT / generate native code for the target machine) - they'll be much faster to load.
So, the project that references those DLLs will link against the assemblies outside the GAC (the ones in the path that you added to the registry key above) but when you run the application, they'll use the assemblies out of the GAC.
-----BEGIN GEEK CODE BLOCK-----
Version: 3.21
GCS/G/MU d- s: a- C++++ UL@ P++(+++) L+(--) E--- W+++ N++ o+ K? w++++ O- M(+) V? PS-- PE Y++ PGP++ t++@ 5 X+++ R+@ tv+ b(-)>b++ DI++++ D+ G e++>+++ h---* r+++ y+++
-----END GEEK CODE BLOCK-----
|
|
|
|
|
First of all, Heath, I'd like to thank you so much for contributing so much to this community. Man, I've opened the C# page, and all the threads I saw were answered by you! Now I'm saying this regardless of whether you answer my question or not. Although I might become nasty if you don't!!! Just kidding
Say I have a number of InternetExplorer objects (say 3). Say I have all of them attached to one DownloadComplete event, which does the following:
1- When I do InternetExplorer.Navigate2(...) any page, this does not stop the code execution, correct? In other words it sort of starts in a different thread?
2- Should I be taking any measures to prevent the DownloadComplete from being accessed while it's already executing? In other words: what happens if one InternetExplorer object finished downloading the document, started executing the code attached in the event handler, and while it's executing it, another InternetExplorer finishes and tries to execute it?
My God, I really sound dumb to myself, I'm sure some people look at this and sigh! Again, thank you for answering.
Sammy
"A good friend, is like a good book: the inside is better than the cover..."
|
|
|
|
|
I think it is safer to start a new thread in that event and do lock and unluck for that string that you process it,cause even each handler run on seprate thread if you have some public variable that changed there it will cause problem or uncorrect data. I hope I was clear.
Mazy
No sig. available now.
|
|
|
|
|
No, I'm sorry, I really didn't get what you meant. May you please illustrate with code?
Sammy
"A good friend, is like a good book: the inside is better than the cover..."
|
|
|
|
|
uhmm,let me explain . Imagine you have a public variable named a. You have two thread than wants to change this value, then what will happend? I'm not sure in the situation that you register one method as an event handler for two control this will happend too.It is called Thread Synchronization . You can see this article to understand more and search CP for other information about threading for more info and samples:
http://www.codeproject.com/csharp/eventsthreadsync.asp[^]
Mazy
No sig. available now.
|
|
|
|
|
Mazdak's idea may work, but another way is to use the lock keyword (or handle synchronization yourself) against an instantiate object (nothing special, you could even lock against the Type):
private void InternetExplorer_DocumentComplete(...)
{
lock (this.GetType())
{
}
} And, yes, Navigate2 is an asynchronous call, hence the need for a DownloadComplete event (as well as other similar events for each element and the document while being parsed).
-----BEGIN GEEK CODE BLOCK-----
Version: 3.21
GCS/G/MU d- s: a- C++++ UL@ P++(+++) L+(--) E--- W+++ N++ o+ K? w++++ O- M(+) V? PS-- PE Y++ PGP++ t++@ 5 X+++ R+@ tv+ b(-)>b++ DI++++ D+ G e++>+++ h---* r+++ y+++
-----END GEEK CODE BLOCK-----
|
|
|
|
|
Thank you Mazdak.
Heath Stewart wrote:
lock (this.GetType())
Why the .GetType()? Shouldn't I obtain a lock against the event sender (of type InternetExplorer)?
Sammy
"A good friend, is like a good book: the inside is better than the cover..."
|
|
|
|
|
You have to lock against the same object (for example, the Type of the current object will always be the same) otherwise the lock doesn't make a difference. Take a look at the System.Threading namespace, specifically the Monitor class (which the lock keyword compiles down to like the following):
Monitor.Enter(syncRoot);
try
{
}
finally
{
Monitor.Exit(syncRoot);
} If the object called syncRoot is different for every call, the monitor will lock against different objects and will not block pending requests to enter the synchronized section.
There are two things you should take into consideration when choosing an object to lock. If you want a method (especially a static method) to be synchronized, lock against a static object (such as the Type, which is recommended, but you can use a static object reference as well). If you want methods to be synchronized only for a given instance, lock against an object member of the instance of your class.
-----BEGIN GEEK CODE BLOCK-----
Version: 3.21
GCS/G/MU d- s: a- C++++ UL@ P++(+++) L+(--) E--- W+++ N++ o+ K? w++++ O- M(+) V? PS-- PE Y++ PGP++ t++@ 5 X+++ R+@ tv+ b(-)>b++ DI++++ D+ G e++>+++ h---* r+++ y+++
-----END GEEK CODE BLOCK-----
|
|
|
|
|
This might take a few words to explain, so please bear with me if you will:
I'm chopping the data of a .WAV file into segments each of length 256 samples. After this segmentation is done, let's say I have N segments. My N by M multidimensional array is called WaveSegments[N,M].
Now, I want to display each of these segments in a UserControl I've made, and want to cycle through the segments by means of an up/down control.
So, for example, clicking once on the up control would change the number from 1 to 2, and the display would change from the samples of WaveSegment[1] to WaveSegment[2].
It seems that using collections would ease coding tremendously, but I seem to be running into any number of syntactical problems.
Could somebody please demonstrate to me how I could do this?
Thank you.
|
|
|
|
|
Actually, using any kind of IEnumerable or IListSource would be great. You can data-bind the collection to the up/down control and use the CurrencyManager.Position property to adjust the position. For more information about data-binding properties and data sources, see Control.BindingContext and CurrencyManager . This would save you from the mess of handling all this yourself. When used correctly, other controls bound to the data source are updated when the position of the current element in the data source is changed.
At any rate, what are the "syntactical" problems? For ease, extend CollectionBase and override the methods (or implement new methods with strongly-typed params that call the CollectionBase 's methods) and most of the rest of the work is already done (which uses an ArrayList to back the elements).
-----BEGIN GEEK CODE BLOCK-----
Version: 3.21
GCS/G/MU d- s: a- C++++ UL@ P++(+++) L+(--) E--- W+++ N++ o+ K? w++++ O- M(+) V? PS-- PE Y++ PGP++ t++@ 5 X+++ R+@ tv+ b(-)>b++ DI++++ D+ G e++>+++ h---* r+++ y+++
-----END GEEK CODE BLOCK-----
|
|
|
|
|
Heath, thanks a lot for your post.
I'm new to programming, and started with C# as that's the language of choice at my company.
Could you give me a code snippet showing how to implement this?
Thanks!
|
|
|
|
|
No need - see the documentation for the CollectionBase class in the .NET Framework SDK (just type "CollectionBase" (without quotes) in the Index) and you'll see an example. Be sure to read the documentation - if not skim it over to see what's available in the base class library - especially when starting out.
-----BEGIN GEEK CODE BLOCK-----
Version: 3.21
GCS/G/MU d- s: a- C++++ UL@ P++(+++) L+(--) E--- W+++ N++ o+ K? w++++ O- M(+) V? PS-- PE Y++ PGP++ t++@ 5 X+++ R+@ tv+ b(-)>b++ DI++++ D+ G e++>+++ h---* r+++ y+++
-----END GEEK CODE BLOCK-----
|
|
|
|
|
Thanks Heath,
Will get back to you if I run into problems.
|
|
|
|
|
Heath, I went over the CollectionBase documents, but I guess it's just not very clear to me.
I've included some of my code below and it would be great if you could help me out.
// Code for class WaveformSegment.
public class WaveformSegment
{
// First we need an object of class "WavFile" to read the contents of the file.
// All data is accessed through objWaveToSegment.Data[]
public WaveFile objWaveToSegment;
// Now we obtain the filename of the file we chose
private string m_FileOpened;
public string FileOpened
{
set { m_FileOpened = value; }
get { return m_FileOpened; }
}
// We now formulate a method to extract the information we need
public void ChopIntoSegments()
{
// Obtain access to the data in the .WAV file
objWaveToSegment = new WaveFile( m_FileOpened );
objWaveToSegment.Read( );
// Definition of multidimensional array WaveSegments
int[,] WaveSegments = new int[17,256];
for(int i = 0; i < 17; i++)
{
for(int j = 0; j < 256; j++)
{
WaveSegments[i,j] = objWaveToSegment.Data[(i*64) + j];
}
}
} // End of ChopIntoSegments()
|
|
|
|
|
You're not overriding the functionality of the CollectionBase like you're supposed to. See the class documentation itself for an example at the bottom of the page.
-----BEGIN GEEK CODE BLOCK-----
Version: 3.21
GCS/G/MU d- s: a- C++++ UL@ P++(+++) L+(--) E--- W+++ N++ o+ K? w++++ O- M(+) V? PS-- PE Y++ PGP++ t++@ 5 X+++ R+@ tv+ b(-)>b++ DI++++ D+ G e++>+++ h---* r+++ y+++
-----END GEEK CODE BLOCK-----
|
|
|
|
|
Heath, I went over the CollectionBase documents, but I guess it's just not very clear to me.
I've included some of my code below and it would be great if you could help me out.
**************************************************
// Code for class WaveformSegment.
public class WaveformSegment
{
// First we need an object of class "WavFile" to // read the contents of the file.
// All data is accessed through
// objWaveToSegment.Data[]
public WaveFile objWaveToSegment;
// Now we obtain the filename of the file we chose
private string m_FileOpened;
public string FileOpened
{
set { m_FileOpened = value; }
get { return m_FileOpened; }
}
// This function performs the segmentation
public void ChopIntoSegments()
{
// Obtain access to the data in the .WAV file
objWaveToSegment = new WaveFile( m_FileOpened );
// Read() is a function in another file, that reads the data in a .WAV file
objWaveToSegment.Read( );
// Definition of multidimensional array
// WaveSegments
int[,] WaveSegments = new int[17,256];
for(int i = 0; i < 17; i++)
{
for(int j = 0; j < 256; j++)
{
WaveSegments[i,j] = objWaveToSegment.Data[(i*64) + j];
}
}
// End of ChopIntoSegments()
**************************************************
Now, I want to write a class SegmentCollection. Here is what I've written so far
**************************************************
public class SegmentCollection : System.Collections.CollectionBase
{
public SegmentCollection()
{}
public void Add( WaveformSegment WaveSegments )
{
this.List.Add( WaveSegments );
}
public int IndexOf( WaveformSegment WaveSegments )
{
return this.List.IndexOf( WaveSegments );
}
public virtual WaveformSegment this [int Index]
{
get
{
return (WaveformSegment)this.List[Index];
}
}
**************************************************
Is this right so far, and how do I access each individual segment?
Thank you.
|
|
|
|
|
I want to display and print excel and pdf in winform ,how to do ? thx.;)
Xpelive
|
|
|
|
|