|
You can't hold me responsible for your actions, consciously nor otherwise. Just keep clicking whenever you feel an urge.
Luc Pattyn [Forum Guidelines] [My Articles] Nil Volentibus Arduum
Please use <PRE> tags for code snippets, they preserve indentation, improve readability, and make me actually look at the code.
|
|
|
|
|
Size doesn't matter... well, not directly anyway.
How many people are working on the project? I prefer to keep files small to reduce the need for multiple developers needing to modify the same file at the same time (an ounce of prevention is worth a pound of cure). The goal, then is to split it up into functional sections, and I do like partial classes. At the extreme (and I know extremes) you can have one method per file, but even I don't go that far (yet). The next thing is to put overloaded versions of one method in one file. And you can put similar methods (like operators) in one file. Basically, I'd say that it's better to have too many parts than too few.
Some of my "largest" classes are Data Access Layers -- all the methods that access tables in a particular database. Unfortunately, with many, I started writing them before partial classes were introduced so each is in one big file . More recent DALs I split into a section for each table. You could, instead, make a section for inserts, another for deletes, etc., but that doesn't seem right. It also doesn't seem right to develop separate classes for each table or action.
So if you have separate files for each table, you can assign Alice to work on Employee methods and Bob to work on Department methods, etc.
|
|
|
|
|
|
One of the goals of programming is clarity. Clarity facilitates software maintenance, and makes code more reliable since it's easier to spot errors. Another (sometimes contradictory) goal is efficiency.
So, if your class split improves clarity or efficiency, it could be the right thing to do.
One measure of clarity is the amount of interaction between the two split classes, called "coupling". If every method in one class depends on, and interacts with something in the other class, the classes are coupled, and this impairs clarity. E.g. to understand a method in one class, you constantly have to bring the other class up on the screen. This breaks your train of thought, and makes consequences of changes less clear.
If the two split classes are independent, with little coupling, splitting them is probably the right thing to do. Small classes are easier to work with than large classes, so this improves clarity.
|
|
|
|
|
If you think you need to ask the question about a class, it is probably time to refactor it.
I wasn't, now I am, then I won't be anymore.
|
|
|
|
|
I have recently posted about the AccessMemoryViolation issue on my WndProc when the usb device is being turned on (or hooked up). This part is solved and runs good.
Now the other thing is that I wonder if there is a way to send the message to WndProc during the startup (WM_CREATE) with the following Parameters:
Message: WM_DEVICECHANGE
WParam: DBT_DEVICEARRIVAL
LParam: DBT_DEVTYP_DEVICEINTERFACE
Code snippet:
----
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Diagnostics;
using HID_API_Library;
namespace USB_Box_Application
{
public partial class Form1 : Form
{
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern int PostMessage(int hWnd, int msg, int wParam, IntPtr lParam);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern int SendMessage(int hWnd, int msg, int wParam, IntPtr lParam);
int[,] deviceInfo = new int[1,2];
Device_Controller dc = new Device_Controller();
DeviceControl[] deviceControl = new DeviceControl[4];
IntPtr[] hwndProcess = new IntPtr[4];
public Point[] PanelLoc = new Point[4];
public Form1()
{
InitializeComponent();
dc.ParentHandle = this.Handle;
dc.RegisterHidNotification(this.Handle);
DisplayPanels();
this.label2.Text = this.Handle.ToInt32().ToString();
SendMessage(this.Handle.ToInt32(), HID_API.WM_DEVICECHANGE, HID_API.DBT_DEVICEARRIVAL, (IntPtr)HID_API.DBT_DEVTYP_DEVICEINTERFACE);
}
private void DisplayPanels()
{
PanelLoc[0] = new Point(0, 0);
PanelLoc[1] = new Point(205, 0);
PanelLoc[2] = new Point(0, 105);
PanelLoc[3] = new Point(205, 105);
for (int i = 0; i < 4; i++)
{
if (deviceControl[i] == null)
deviceControl[i] = new DeviceControl();
deviceControl[i].Location = PanelLoc[i];
try
{
deviceControl[i].DeviceHandle = dc.cbInfos[i].usbHandle;
deviceControl[i].DeviceBoxId = dc.cbInfos[i].boxID;
deviceControl[i].DeviceProductId = dc.cbInfos[i].productId;
deviceControl[i].DeviceVendorId = dc.cbInfos[i].vendorId;
deviceControl[i].DeviceConnected = true;
}
catch
{
deviceControl[i].DeviceHandle = -1;
deviceControl[i].DeviceBoxId = -1;
deviceControl[i].DeviceProductId = -1;
deviceControl[i].DeviceVendorId = -1;
deviceControl[i].DeviceConnected = false;
}
}
this.Controls.AddRange(deviceControl);
}
protected override void WndProc(ref Message m)
{
switch (m.Msg)
{
case 0x0001:
{
dc.RegisterHidNotification(this.Handle);
SendMessage(this.Handle.ToInt32(), HID_API.WM_DEVICECHANGE, HID_API.DBT_DEVICEARRIVAL, m.LParam);
break;
}
case HID_API.WM_DEVICECHANGE:
{
switch (m.WParam.ToInt32())
{
case HID_API.DBT_DEVICEARRIVAL:
{
OnDeviceChange(m);
break;
}
case HID_API.DBT_DEVICEREMOVECOMPLETE:
{
RemoveDevice(ref m);
break;
}
}
break;
}
}
base.WndProc(ref m);
}
void OnDeviceChange(Message m)
{
switch (m.WParam.ToInt32())
{
case HID_API.DBT_DEVICEARRIVAL:
{
DEV_BROADCAST_HDR hdr = (DEV_BROADCAST_HDR)m.GetLParam(typeof(DEV_BROADCAST_HDR));
if (hdr.dbch_devicetype == HID_API.DBT_DEVTYP_DEVICEINTERFACE)
{
DEV_BROADCAST_DEVICEINTERFACE1 dbd = (DEV_BROADCAST_DEVICEINTERFACE1)Marshal.PtrToStructure(m.LParam, typeof(DEV_BROADCAST_DEVICEINTERFACE1));
string usbDevice = new string(dbd.dbcc_name);
if (usbDevice.Contains("Vid_1238&Pid_5000"))
label2.Text = "USB Box Found!";
if (usbDevice.Contains("Vid_0483&Pid_0003"))
label2.Text = "Clear Box Found!";
SECURITY_ATTRIBUTES securityAttrib = new SECURITY_ATTRIBUTES();
int usbHandle = HID_API.CreateFile(usbDevice, HID_API.GENERIC_READ,
HID_API.FILE_SHARE_READ | HID_API.FILE_SHARE_WRITE,
ref securityAttrib,
HID_API.OPEN_EXISTING,
HID_API.FILE_FLAG_OVERLAPPED, 0);
if (usbDevice.Contains("Vid_1238&Pid_5000"))
MessageBox.Show(string.Format("{0}: {1} {2}", "USB Box Found", "Handle =", usbHandle));
if (usbDevice.Contains("Vid_0483&Pid_0003"))
MessageBox.Show(string.Format("{0}: {1} {2}", "Clear Box Found", "Handle =", usbHandle));
}
break;
}
}
}
|
|
|
|
|
Hi again,
1.
your code still is not correct, you're still sending a phony pointer in your Form's constructor.
2.
why would you want to send it earlier than you are already doing? if you must, you could send it from inside the static Main method, however it would not get processed by your Form yet, as it does not exist yet.
BTW: you could work without the SendMessage, just trick your WndProc so that it mimics the receipt of whatever it is you want the first time it is called...
Luc Pattyn [Forum Guidelines] [My Articles] Nil Volentibus Arduum
Please use <PRE> tags for code snippets, they preserve indentation, improve readability, and make me actually look at the code.
|
|
|
|
|
This "sendmessage" is an example... i know that this line has phony pointer.
How do I trick WndProc that it would mimic the receipt for the first time it is called?
|
|
|
|
|
Elementary:
bool firstMessage=true;
override WndProc(...) {
if (firstMessage) {
firstMessage=false;
...
}
...
}
Luc Pattyn [Forum Guidelines] [My Articles] Nil Volentibus Arduum
Please use <PRE> tags for code snippets, they preserve indentation, improve readability, and make me actually look at the code.
|
|
|
|
|
i'm developing a simple socket application for server client architecture. it works fine when the
pc is having a static it , but when the pc is obtaining Ips automatically means when the radio button for
"obtain an ip autmatically" , it gives the exception saying this ip is not valid in the context ,
any idea to address this situation.
thanx in advance.
|
|
|
|
|
Can you use machine name instead of IP address. As you indicated the IP address can be changed when it is using dynamic IP setting, where as the machine name stays the same.
|
|
|
|
|
Which IP address are you referring to here, the local or remote? If it is the remote address then you need to verify that it is consistent with the actual address in use by the remote machine. Perhaps if you show an extract of your code, and what results you are seeing, we can offer some further suggestions.
I must get a clever new signature for 2011.
|
|
|
|
|
thanx for all of you ..!
and this is the code segment i use.
localIP = Dns.GetHostAddresses(Dns.GetHostName())[0];
IPEndPoint localEndpoint = new IPEndPoint(localIP, 7575);
lSoc = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
lSoc.Bind(localEndpoint);
lSoc.Listen(10);
|
|
|
|
|
You need to go through this code with your debugger and see exactly what values are being returned for the IP address.
I must get a clever new signature for 2011.
|
|
|
|
|
In a client server architecture the 'server' IP is traditionally fixed. Not dynamic.
In a client server architecture the client connects to the server.
If the server IP is not fixed then one must use another mechanism which will require some other server to get the current IP. Host name resolution is one method to do that. It does however require that the host name is being managed by a DNS server.
|
|
|
|
|
I'm not sure what the equivalent terminology would be for this but I'm looking for a way to achieve a way of returning a reference type from a method but preventing the user from modifying the public properties or mutators of that type (without some explicit casting away of const or whatever the equivalent approach might be in C#).
Basically, is there a way to at least state my intent in the code and maybe get some level of help from the compiler in discouraging any mutations on the object using that reference? I understand that nothing is fool proof but any assistance from the compiler in enforcing my intentions is always welcome to protect me from myself down the road when jacking with the code.
thanks.
|
|
|
|
|
AFAIK there is no way unless the fields of your reference type field are also readonly. See this[^] at msdn.
|
|
|
|
|
Hi,
you can't in general. Some objects may have provisions for turning themselves into some kind of read-only state, e.g. a generic list can be declared read-only meaning you can't modify the list, but then you still can modify the list items themselves.
Luc Pattyn [Forum Guidelines] [My Articles] Nil Volentibus Arduum
Please use <PRE> tags for code snippets, they preserve indentation, improve readability, and make me actually look at the code.
|
|
|
|
|
Proxy it:
Return a interface which only provides readonly access.
You create the real object and the you create a proxy using the interface which encapsulates the real object.
|
|
|
|
|
A very interesting thought. I'm going to have to try this and see if it is practical.
I wasn't, now I am, then I won't be anymore.
|
|
|
|
|
I think this is the way I'm going to have to do it as some of the members can't be initialized via the constructor. I need to assign a couple later on in the process so "friend" would have been nice (NOTE: "internal" does not allow specifics and putting a few of these classes in another assembly is overkill for my small projects).
Later on I need to let other classes access these objects so that is where I'd love to mark a const intention. I guess I'll pass back the interface to achieve this.
I'm really surprised C# does not implement such useful idea such as "const" (As it exists in C++ that is) as it helps the compiler help me reduce inadvertant mistakes today and years down the road during code maintenance.
Anyway, thanks for the advice.
|
|
|
|
|
Apart from what has been mentioned above, the only other way I can think of is to clone the object. Client code will still be able to change values but at least the original object wont change.
Another alternative is to create a read only version of the class and return that.
Architecture is extensible, code is minimal.
|
|
|
|
|
I'm just trying to let other classes have access to the data in the object so cloning would cost too much. The process will need to access the data enough that I only want to pass references around for efficiency.
Creating a read-only version would only be possible if all the data were available to the constructor but unfortunately the process requires a few stages to fully initialize the objects so a few properties need to be accessible by other classes. Since "friend" doesn't exist in C# and since making it "internal" and placing those classes in a different assembly seems like overkill, I'm just going to create an interface to implement that only provides accessors and pass a reference of that interface around to make the const intention apparent in the code.
Someone had suggested using the interface earlier in the other threads and I had come across the same idea on StackOverflow earlier in the day and thought it was a reasonably elegant way to emulate const correctness in C#. However, it turns out to be more work than it should be for something so fundamental to helping the compiler understand the orginal programmers intentions IMHO.
C# had been nothing more than a curiosity to me until recently as I stuck with C/C++ all these years but now that I've attempted to write a few small but serious apps with C#, I'm realizing it's really lacking in some important ways. I've read the posts, blogs, and documentation defending some of the design decisions but I've seen some good counter arguments as well.
Anyway, enough of my ranting. I'll probably need to work with it some more before getting too critical of it.
thanks for the advice.
|
|
|
|
|
Just as a side note: In Visual Studio you can extract an interface from a class by viewing the class in the editor and then Ctl + R,I
Architecture is extensible, code is minimal.
|
|
|
|
|
... and then remove the property set blocks and the functions which could change the data, and access the object via this "read-only interface". Nice idea, and easy to implement!
|
|
|
|
|