|
Hi all,
Our current applications use MFC Serialize to create our files, using the standard MFC rules.
The bosses that be wish our new .NET apps to read in these old files so we have an upgrade path for our users.
Is there an easy way to read in the MFC created file in a way much like the MFC Serialize function? i'd prefer not to have to read it in as a binary stream and work on it that way?
Any ideas?
Thanks
|
|
|
|
|
Runtime serialization definitely won't be any help since it is tied to Types. You can either read it in as a binary stream either with your app or through some convert app (which I know you don't want to do, but there's not a lot of choices) or develop an MC++ mixed-mode assembly that can - if possible - use your original MFC classes to deserialize the stream and construct managed classes from that data, which you can then serialize using Runtime Serialization. These classes could even be defined in a C# assembly if you want to create a conversion application.
Using MC++ would definitely be much easier since you can mix native and managed code, thus easily using your original MFC classes while also using managed classes from another assembly.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
The mixed mode assembly is a good idea, i'm not sure it would work for us though as we have a very large number of objects we would have to recreate, and we may end up referencing almost all of the MFC app which i know my boss won't like, but i'll certainly look into it though thanks.
Seems odd that MS didnt offer us something better than a binary stream but not quite runtime serialization?
|
|
|
|
|
If you want to deserialize your old MFC stream, then wouldn't that imply you plan on recreating many of these classes in C# anyway? Also, this MC++ could simply be a conversion program so that the old MFC classes aren't need to run your actual application which requires the deserialized stream.
MFC Serialization is specific to MFC while Runtime Serialization is specific to the Runtime. They work very differently and at the time MFC serialization was designed, something like XML was a pipe-dream. .NET can also use XML Serialization (more basic, but sometimes that's good) and Runtime Serialization using either the binary or SOAP formatters provided in the FCL, or any custom formatter you or someone else could create. It's a very extensible system.
The fact is that they both work very differently.
It would be possible to create, for example, an IFormatter class that could deserialize your MFC stream and maybe even stick with the same schema, but that's quite a bit of work and still requires that you handle the binary stream from your MFC app. If you upgrade to newer technology, change is inevitable or your force to design your app to the lowest common denominator - your old MFC app.
For this new application, you may wish to look at SOAP formatting using Runtime Serialization (more powerful), or simple XML Serialization. This will allow you to easily convert to something else in the future using the XML DOM or transforming it using XSLT. XML is around to stay for quite some time. While it's not always the most compact solution (see discussions on SOAP vs. Binary formatting across remote boundaries), it's definitely extensible.
For more information on these two alternatives, see XML and SOAP Serialization[^] in the .NET Framework SDK.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
The .NET application is heavily Xml based and we use Xslt heavily aswell, mainly for the reasons you have described.
The app will be structured better than our old MFC app as over the years (and programmers) its eaten way to many pies, but thinking about it more your idea of a MC++ app is probably the best option, that way we can get at MFC classes to get the data in then from the file and then convert it to an Xml doc that our new app likes, but by having it as a seperate tool we don't have to stick to the same class heirachy as the old app.
Thanks for the tip
|
|
|
|
|
Greetings all,
My goal: write a TreeNode class that contains another object and have the display text for the TreeNode be automatically set to some method on the object. Psuedo-ish code:
public class DerivedNode : System.Windows.Forms.TreeNode
{
public MidTierClassLib.SomeClass oObject;
public DerivedNode(MidTierClassLib.SomeClass SomeObject)
{
this.oObject = SomeObject;
}
public new string Text
{
get
{
return (this.oObject.ToString ());
}
}
}
Trouble is: When I add a new DerivedNode to my TreeView, the text is blank. Stepping through in the debugger shows that the get clause is never called. This suggests I am barking up the wrong tree...
Ideally, I want to be able to change properties on oObject and have the display updated automagically. I am pretty green with using TreeViews and TreeNodes (pun intended)...couldn't find anything that looked like a databinding...so any guidance would be appreciated.
Thanks in advance,
Bill
|
|
|
|
|
public DerivedNode(MidTierClassLib.SomeClass SomeObject)
{
this.oObject = SomeObject;
base.Text = SomeObject.ToString();
}
---------------------------
He who knows that enough is enough will always have enough.
-Lao Tsu
|
|
|
|
|
Thanks Judah,
Clearly that'll do it on construction. But that won't help afterwards. Sometime later when I set a property on the oObject, I want the DerivedNode's Text property to be automatically updated as a result.
I am thinking about adding an event to the oObject that it can raise whenever a change that needs to be displayed happens. That'll work but it breaks the division between mid-tier and GUI (the oObject should not explicitly tell the GUI when to do anything).
Bill
|
|
|
|
|
Then in the set accessor for that object's property, also set the DerivedNode.Text property, which means you'll have to pass an instance of the DerivedNode to the other object:
public class DerivedNode : TreeNode
{
private SomeObject someObject;
public DerivedNode(string text)
{
someObject = new SomeObject(this);
Text = someObject.SomeProp;
}
}
public class SomeObject
{
private DerivedNode node;
private string someProp;
public SomeObject(DerivedNode node)
{
this.node = node;
}
public string SomeProp
{
get { return someProp; }
set
{
someProp = value;
if (node != null) node.Text = someProp;
}
}
}
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Thanks Heath,
...but that's not an appealing option either... (ain't I fun to help?!?). The objects need to be able to function without the gui. For example we may need to use then in Console applications for data maintainence or to slice and dice the data in other ways through WebApps, etc, so I think I favor the event-base approach since other application can just ignore the events.
That said, do you know why the get accessor on the DerivedNode.Text property is not called when the node is displayed? That bit baffles me.
Bill
|
|
|
|
|
Then using events would be the logical way to go.
The reason the get accessor is not called is because the TreeView uses the TreeNode type. Its Text property is not virtual so the IL instruction call is used, as opposed to callvirt . Even if you hide it using the new operator, this will not work because the TreeView is using call on the actual TreeNode type. If you were to get the Text property referencing your type (DerivedNode ), then your get accessor would be called.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Thanks again Heath,
As per the usual: you told me what I needed to know. I'll post a generic version of what I come up with here so maybe future TreeNode-noobs won't have to take up forum-bandwidth.
Out,
Bill
|
|
|
|
|
Hello All
I am on a project that is analogous to a game in which you are tasked to draw the number of students on campus as if you are looking from a helicopter. The students can disappear from the screen as they get into classes or buildings and more students can also added as they try to get to classes from outside campus.
I have tried to use the cirular buffering technique to buffer the total number of students at one moment and display the contents on the screen. Let's say that I have a timer that ticks every 100msec which then will try to paint the location of the student on campus.
But then the problem comes when the program tries to get the student objects from the buffer which is a collection of ArrayList's. It kept telling me that the index in the ArrayList that it's trying consume has changed. I couldn't think of how to get around it now. If you could point out what is wrong with my code, or suggest any other technique, it would be very appreciative.
Below is the code similar to mine:
public class Student
{ public string a,b,c; public int id,x,y,z;}
public class CBuffer
{ ArrayList[] buffArrayList = {null,null,null};
int occupiedBufferCount;
public ArrayList BufferSet
{
get
{
lock(this)
{
if (occupiedBufferCount == 0)
Monitor.Wait(this);
ArrayList readValue = buffArrayList[readLocation];
--occupiedBufferCount;
readLocation = (readLocation +1)%buffArrayList.Length;
Monitor.PulseAll(this);
return readValue; } }
set
{
lock(this)
{
if(occupiedBufferCount == buffers.Length)
Monitor.Wait(this);
buffArrayList[writeLocation] = value;
++occupiedBufferCount;
writeLocation = (writeLocation + 1) % buffArrayList.Length;
Monitor.PulseAll(this); } } }
public class Consumer
{ private ArrayList ar;
private CBuffer buff;
Graphics g;
public void Consumer(CBuffer _buff, Graphics _g)
{ buff = _buff; g=_g; }
public void TestDraw()
{
PaintBground();
ar = new ArrayList();
ar = buff.BufferSet;
foreach (Student s in ar)
DrawStudentLocationOnScreen(); }
private void DrawStudentLocationOnScreen(){ ..codes..} }
public class Producer
{ private ArrayList ar;
private CBuffer buff;
public void Producer(CBuffer _buff)
{ buff=_buff;}
public void Produce()
{
GetStudentsFromFile();
ar.Add(student);
buff.BufferSet = ar; }}
|
|
|
|
|
Short answer: You can't do this easily with ArrayLists. With an ArrayList, you can't simultaneously modify and iterate through the collection.
Since you're dealing with a fixed-size buffer, why don't you use a standard array? (ie, Student[] ar = new Student[length]; )
Jeremy Kimball
magnae clunes mihi placent, nec possum de hac re mentiri.
(Large buttocks are pleasing to me, nor am I able to lie concerning this matter)
|
|
|
|
|
Jeremy,
I've thought about your suggestion before. But I think when my timer ticks every 100msec, the number of students and the variables in the Student objects will also change. So I think it wouldn't work in this case. However, if you have a game with fixed number of players or objects on the screen, fixed-size buffer would definitely work.
Thanks,
Tim
|
|
|
|
|
Multithreaded programming is extremely difficult. Even those who are consider experts at it frequently make mistakes. The producer/consumer problem isn't trivial. It is most easily solved with semaphores[^].
public class Buffer
{
private int in = 0;
private int out = 0;
private object[] buffer = new object[CAPACITY];
private Semaphore full = new Semaphore(CAPACITY);
private Semaphore empty = new Semaphore(0);
private Semaphore mutex = new Semaphore(1);
<br>
public object Thing
{
get
{
mutex.WaitOne();
empty.WaitOne();
object t = buffer[out];
out = (out + 1) % buffer.Length;
full.AddOne();
mutex.AddOne();
return t;
}
set
{
full.WaitOne();
mutex.WaitOne();
object t = buffer[in];
in = (in + 1) % buffer.Length;
buffer[in] = value;
mutex.AddOne();
empty.AddOne();
}
}
}
Notice that this implementation isn't trivial. Furthermore, the Semaphore implementation isn't trivial either.
|
|
|
|
|
Thanks, Brian!
I think you are pointing me to the right direction. Never before I had to use this so I'm going to have to some reading. I've just read some on semaphore on MSDN. So, I think it'll take me some time to fully understand and put together a Semaphore object
Regards,
Tim
|
|
|
|
|
It'll take some time to fully understand so be patient. Fortunately the link I provided is for a Semaphore object that has already been coded by a Microsoft employee so you shouldn't have to put one together yourself. Good luck.
|
|
|
|
|
Didn't realize there was a link on "Semaphore" in your first msg. My fault.
Cheers
|
|
|
|
|
I would like to force DataGrid to use my implementation of IComparer when sorting columns.
Can anyone give me some ideas on how to achieve that if possible at all??
Dries
|
|
|
|
|
String.Compare is used internally by the DataView.Sort property (in the set accessor) with no way to override it.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Out of curiosity, could you derive a class from DataView (dunno if it's sealed or not, too lazy to open up studio right now) and override the Sort property?
Jeremy Kimball
magnae clunes mihi placent, nec possum de hac re mentiri.
(Large buttocks are pleasing to me, nor am I able to lie concerning this matter)
|
|
|
|
|
It's not virtual, so you'd have to hide it, but the controls like the DataGrid will indirectly refer to your type as a DataView , meaning that its definition of Sort would be used.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Ah bugger...you could always decompile System.Data.dll, modify the IL, then recompile it
Jeremy Kimball
Catapultam habeo. Nisi pecuniam omnem mihi dabis, ad caput tuum saxum immane mittam.
(I have a catapult. Give me all the money, or I will fling an enormous rock at your head)
|
|
|
|
|
Does anyone know how to synchronize 2 database files
(apply the changes on both) in C#
I've tried to add to project references to both Microsoft Active Data Objects 2.7 and Microsoft Jet Replication Objects (2.6?).
and I've read some examples in VB
ms-help://MS.VSCC.2003/MS.MSDNQTR.2003FEB.1033/dnacc2k/html/jrorep.htm
it didn't help much

|
|
|
|