|
malharone wrote: I couldnt agree with you more on this point. But there are cases when from you non-generic class, you want to call a generic method and all you want do is to pass the "current type" and not any other type. In most cases, you will hard-code the class name, but if you're working in the base class, you would not know the type of the deriving class.
I think there's a conceptual problem here. First of all, you can overload your method if you need to process a handful of known classes, or you can simply let descendants override your method (if they need to), and whatever calls the method ends up firing, being as they belong to the instance you (or whoever) calls them on, this ends up firing the method implementation of the closest descendant to the class it's called on (which may be the instance class itself). As your class design is a matter of writing these methods *for each class* (if necessary to override them), this *is* the right method (whether overloads or overrides are necessary or not -- they may very well not be).
Now, if you need to identify the class otherwise (which isn't evident from your example), you can also pass your own identifier argument. It doesn't even have to be a real class -- it could be an enumerated type... anything, even an integer. C++ guys do this all the time to eliminate dynamic casting, and it's perfectly sound if you cover your bases... and faster than greased things unmentionable in C# forums.
Reflection will also work to determine the class (although I have to admit I'm a bit raw with this with C#, as it's something I'll be getting to in the near future). I know for instance I have substantial notes and collected material on the Activator class, which I intend to use to create instances of unknown classes, which certainly is an intersecting area.
-----
Now, I also have another thought. You have a mixture of generics and non-generics interacting. Something you wrote earlier also tells me you are flexible -- you could write this as all non-generic then?
If you can, that's a good way to work out the problem. Get it working without generics. This will tell you exactly how to build generics into it, if that is a good thing to do.
It probably is a good thing to do if you have to do any casting, because it can eliminate casting altogether, and provide wholy type safe operation with minimal code.
I really can't see what the problem is. I look at your question, and you say you have to pass the type, and I ask myself, is he trying to call a static method without an instance (which is a place where the method doesn't know what type it belongs to, because there is no inherent this or instance pointer). Otherwise, a method always knows what type it belongs to, and doesn't need to reference the type. So unless a method has to process a further type which hasn't been cast for processing, I have yet to see in your question why you can't get the job done one of these ways.
Actually, you say:
malharone wrote: The only workaround for this limiation, is to make the method from your base class abstract and let the deriving classes implement the call.
So we are in complete agreement. Why then can't you let that method call preciptate to the descendant, which, if it had needed to, has revised the method to handle itself however necessary? That's just general practice.
|
|
|
|
|
PS.
My own use of (or need to use) generics has never encountered any challenging hurdle that I can't just write them at will -- and any usage has always been very straightforward. I still think you have a basic conceptual class design problem, but just in case you might find deep generic study helpful, I think Richter is a truly excellent source (CLR Via C#, Second Edition). On p. 374, you will find an excellent chapter on Generic Methods. On p. 375, there is an excellent subtitle on Generic Methods and Type Inference. Much further material addresses everything you need to know about generics. I highly encourage you to use them for the same reasons Richter does -- processing is inherently much faster, because casting/boxing are eliminated (he cites many examples, and practice proves they are quite correct). Good programming will always use them where they benefit a project in this way -- generics are unavoidable necessities to good practice. But they really aren't that difficult.
|
|
|
|
|
Just for example (before I get back to work),
Here's a declaration from current work which is not really difficult to grasp. It's declaring an outer generic container of 2 levels of inner generic containers. What are the ramifications of this? Not much, really. It just allows me to do a lot of work without casting -- which in fact is very important to high speed iterative processes which have to act very often on each internal instance.
protected List<List<List<Bitmap>>> v_Maps_MASTER = new List<List<List<Bitmap>>>( );
This is just a container for further generics which are declared like this:
protected List<Bitmap> v_Maps_Button_UP = new List<Bitmap>( );
In the end however, every member is just a bitmap, and therefore every instance can be called just as "if" it is a bitmap, because *it IS* a bitmap ("generic" or not):
if ( ( enumContours.TopAndBottom == f_Contours ) || ( enumContours.TopOnly == f_Contours ) )
{
v_Maps_UP[ i_Btn_BL_BR ][ i_NF ].SetPixel( 0, 0,
Color_IncOrDecLum( v_cBaseUP_Glossed, lumDiffAccumulated_I + f_LumDif_EdgeBevels ) );
}
else
{
v_Maps_UP[ i_Btn_BL_BR ][ i_NF ].SetPixel( 0, 0,
Color_IncOrDecLum( v_cFLATFILL_UPContours, lumDiffAccumulated_I + f_LumDif_EdgeBevels ) );
}
So this is just basic practice. Generics just help us process *a class* (or classes, as they are usually processed).
|
|
|
|
|
PS.
*If one or however many of the instances descended from Bitmap, it still could legally be assigned to the instance pointer comprising each "member." If my methods act on that instance, and if it overrides a Bitmap method that I call, the proper method is automatically called.
|
|
|
|
|
malharone wrote: But there are cases when from you non-generic class, you want to call a generic method and all you want do is to pass the "current type" and not any other type.
Whenever you need to do this, this is the way to write your call:
( CurrentType )InstanceReference.Method( args )
|
|
|
|
|
malharone wrote: WHAT SHOULD GO HERE
The name of a class.
You could use the name of the base class DomainObject .
|
|
|
|
|
Yes, the name of the class would go in the place holder. But it would be the name of the concrete type as opposed to hard-coding base type.
E.g.
If I have Car c = new Car();
and when I perform c.Delete() operation, I'd like to be able to execute _dbStore.DeleteObject<Car>(_id) from the DomainObject .
If I have Boat b = new Boat();
and when I perform b.Delete() operation, I'd like to be able to execute _dbStore.DeleteObject<Boat>(_id) from the DomainObject .
I just dont know how I could dynamically "pass" the runtime class name to the generic method in DBStore.
- Malhar
|
|
|
|
|
I am not sure if this is what you want:
<br />
class DBStore<T> where T : class, new()<br />
{<br />
public T CreateObject()<br />
{<br />
return new T();<br />
}<br />
public void DeleteObject<T>(int id)<br />
{<br />
Type t = typeof(T);<br />
}<br />
public DBStore()<br />
{<br />
}<br />
}<br />
abstract class DomainObject<T> where T : class, new()<br />
{<br />
protected int _id;<br />
protected DBStore<T> _dbStore;<br />
public void Delete ()<br />
{<br />
_dbStore.DeleteObject<T>(_id);<br />
}<br />
}<br />
class Boat : DomainObject<Boat><br />
{<br />
public Boat()<br />
{<br />
}<br />
public Boat(int id)<br />
{<br />
this._id = id;<br />
this._dbStore = new DBStore<Boat>();<br />
}<br />
}<br />
class Car : DomainObject<Car><br />
{<br />
public Car()<br />
{<br />
}<br />
public Car(int id)<br />
{<br />
this._id = id;<br />
this._dbStore = new DBStore<Car>();<br />
}<br />
}<br />
<br />
class TestClass<br />
{<br />
public void Run()<br />
{<br />
Boat boat = new Boat(1234);<br />
boat.Delete();<br />
<br />
Car car = new Car(5678);<br />
car.Delete();<br />
}<br />
}<br />
|
|
|
|
|
I think the forum software treated the <s & >s as HTML tags. Do you mean the following instead?
abstract class DomainObject <T> where T : class, new() and
class Boat:DomainObject<Boat> and
class Car:DomainObject<Car>
I have two nags now (nohing major):
a) change method signature from ListViewItem GetItem (DomainObject o) to ListViewItem GetItem (DomainObject <DomainObject> o) in non-generic classes (such as list views)
b) redundancy in class declaration: class Car:DomainObject<Car>
Any opinions?
I think you also meant to genericise the DBStore class, but the lts & gts were converted to HTML. Anyways, in my case, I am planning on keeping the DBStore a non-generic singleton. So, only the methods in it will have generic declaration.
Nonethelss, thanks for your previous suggestion.. I didnt know about the class keyword. i'll look into it!
- Malhar
|
|
|
|
|
If I'm not mistaken, then you're suggesting something like:
public abstract class DomainObject<T>
This will break majority of the app where I'm simply keeping a reference to the base DomainObject as opposed to DomainObject for Car. You could help clarify my misunderstanding .. but:
Assuming I changed the class declaration as above (with generics), what should I change my dependent method signature for the classes that do NOT inherit from generics?
e.g.
01. class ListViewEx
02. {
03.
04. DomainObject _selectedObject;
05.
06. public void AddItem (DomainObject obj)
07. { ... }
08.
09. public DomainObject SelectedObject
10. { get { return _selectedObject; }
11. set { ... } }
12.}
- What should the line #4, 6 & 9 look like after genericising DomainObject?
- And one thing to note is that currently, ListViewEx.AddItem is designed to allow consumer to pass both objects of type Car AND Boat. If I genericize the ListViewEx to class ListViewEx <T> then a. I'll lose the functionality of adding items of multiple types, and b. Win form designer will no longer work.
Thanks,
- Malhar
|
|
|
|
|
I am having to strip some info from some text files to dump into a data table. The problem, well, not a problem, but a nuance, is that the information needed from these text files are at the very end of the file, which average about 400K.
Here is the code I am using:
objRead = new StreamReader(m_strFileName);
while (objRead.Peek() > -1)
{
strRecord = objRead.ReadLine();
if (strRecord.Length > 20)
{
if (strRecord.Substring(44,3) == "NEW")
{
if (strRecord.Substring(87,11) != " ")
{
decDepr[0] = Decimal.Parse(strRecord.Substring(87,11));
}
else{decDepr[0] = 0;}
}
You get the idea...
The question is can I start reading from the end of the file or is there a smarter way to do this? I am having to repeat this process 22 times for 22 different reports, which takes some time.
Thanx in advance!
Jude
|
|
|
|
|
from this code, it seems that whether the data is in the end or start it will take the same time, since you are continuing the loop even after getting the data. so i do not see any difference in time even if you start reading from bottom.
Regards
Shajeel
|
|
|
|
|
Well, if I do start reading from the bottom I will get the information I need then be able to close the stream read and go on to the next file. The data that needs to be read is at the very bottom of the file. I just don't know how to start reading from the end of the file.
Thanx for the reply!
Jude
|
|
|
|
|
Hi,
have a look at FileStream.Seek() or FileStream.Position which will allow you to read
into a byte[] the last N bytes of a file.
|
|
|
|
|
I have some problems with microsoft´s example under void GetObjectData(SerializationInfo info, StreamingContext context) in MSDN VS5. I have executed the code and it´s running, but when I remove formatter.Serialize(fs, a1) and try to Deserialize the binary file, it fails.
Have I misunderstod the example or What is wrong? Can I fix the code I need to serialize a singleton.
Best regards, Gywox
Modified Example:
<br />
using System;<br />
using System.Web;<br />
using System.IO;<br />
using System.Collections;<br />
using System.Runtime.Serialization.Formatters.Binary;<br />
using System.Runtime.Serialization;<br />
using System.Security.Permissions;<br />
<br />
[Serializable]<br />
public sealed class Singleton : ISerializable<br />
{<br />
private static readonly Singleton theOneObject = new Singleton();<br />
private string someString_value;<br />
private Int32 someNumber_value;<br />
<br />
public string SomeString<br />
{<br />
get<br />
{<br />
return someString_value;<br />
}<br />
set<br />
{<br />
someString_value = value;<br />
}<br />
}<br />
<br />
public Int32 SomeNumber<br />
{<br />
get<br />
{<br />
return someNumber_value;<br />
}<br />
set<br />
{<br />
someNumber_value = value;<br />
}<br />
}<br />
<br />
private Singleton()<br />
{<br />
}<br />
<br />
public static Singleton GetSingleton()<br />
{<br />
return theOneObject;<br />
}<br />
<br />
[SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter)]<br />
void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)<br />
{<br />
info.SetType(typeof(SingletonSerializationHelper));<br />
}<br />
}<br />
<br />
<br />
[Serializable]<br />
internal sealed class SingletonSerializationHelper : IObjectReference<br />
{<br />
public Object GetRealObject(StreamingContext context)<br />
{<br />
return Singleton.GetSingleton();<br />
}<br />
}<br />
<br />
class App<br />
{<br />
[STAThread]<br />
static void Main()<br />
{<br />
FileStream fs = new FileStream("DataFile.dat", FileMode.OpenOrCreate);<br />
<br />
try<br />
{<br />
BinaryFormatter formatter = new BinaryFormatter();<br />
<br />
Singleton[] a2 = (Singleton[])formatter.Deserialize(fs);<br />
Console.WriteLine("Do both array elements refer to the same object? " + (a2[0] == a2[1]));<br />
Console.WriteLine(a2[0].SomeString + " " + a2[0].SomeNumber);<br />
Console.WriteLine(a2[1].SomeString + " " + a2[1].SomeNumber);<br />
}<br />
catch (SerializationException e)<br />
{<br />
Console.WriteLine("Failed to serialize. Reason: " + e.Message);<br />
throw;<br />
}<br />
finally<br />
{<br />
fs.Close();<br />
}<br />
}<br />
}
|
|
|
|
|
Below is what I use for serialization. It seems to work fine for me?
public void GetObjectData(SerializationInfo info, StreamingContext context){
info.AddValue("id", id);
info.AddValue("applicationId", applicationId);
}
public MyObject(SerializationInfo info, StreamingContext context) {
id = info.GetInt64("id");
applicationId = info.GetInt64("applicationId");
}
File Not Found
|
|
|
|
|
Hi!
Some source code, please.
How do you manage to Serialize/Deserialize a Singleton?
Singleton.Instance = (Singleton)formatter.Deserialize(fs); // Error Singleton is readonly
/Gywox
|
|
|
|
|
Use the System.Xml.Serialization.XmlSerializer class to serialize. As for managing a Singleton that is not a serialization issue but a design issue. But for grins and giggles, in the serialization constructor overwrite your static instance for the singleton.
formatter.Deserialize(fs);
public SomeConstructor(SerializationInfo info, StreamingContext context) {
...
SomeConstructor.me = this;
}
File Not Found
|
|
|
|
|
Hi, I got stuck in a problem and don't know what to do. In my web form. I am trying to display a ModalPopup window(Ajax) when I click on a link button. It gets displayed behind the flash image object which i have in the center of my web form. The modalpopup works completely fine if i remove the flash image object.
I need to make this working is there a way to do. Please help me
Thanks
|
|
|
|
|
I was trying to allow a user to resize one of the panels on my form (by moving arrowicons). However I get these errors.
'System.Windows.Forms.Control.Location' because it is not a variable
'System.Windows.Forms.Control.Size' because it is not a variable
here is what I was trying to do:
AOIpanel.Location.X = leftEdgeArrow.Location.X;
AOIpanel.Location.Y = (centerArrow.Location.Y +(AOIpanel.Size.Height/2));
AOIpanel.Size.Width = (rightEdgeArrow.Location.X - leftEdgeArrow.Location.X);
-- modified at 16:24 Wednesday 21st February, 2007
|
|
|
|
|
Hi,
setting Control.Location.X or Control.Size.Width does not help
(see the remark at Control.Location).
if you want to change the Location or Size you must either use "new Point()" or "new Size()",
or the properties Left, Top, Width, Height.
But it would not generate the errors you mention either (unless the code you are showing is not
actually the code you are compiling). I assume you tried to use Location.X etc. as an
out or ref parameter, which is impossible, out/ref requires a variable, a struct or
a class object, but not a part of them (such as a struct field).
|
|
|
|
|
Hi Guys!
I am having a weird problem with one of our computers here at work, my application uses crystal report viewer with C# application designed in VS2003. All computers print the report just fine but this one computer prints a few rows and columns and then cuts off the rest of the print and if the user goes back and tries to print again the same report then it prints just fine. I am not sure why this is happening, could it be the printer driver.
PLEASE HELP!!!
sasa
|
|
|
|
|
Is it possible to make the mouse pointer follow moving objects on the screen?
|
|
|
|
|
|
I have an application that save some sort of information in a an xml file. I want to control that application remotely so I want to save that xml file in a web service.
I want to how I can save an xml file via a web service
|
|
|
|
|