As I can't use true multiple inheritance in C#, how would I design
this to be able to share the methods and properties?
This is the right way to share the methods and properties. But:
The trouble now is that in my extendedTextBox class I can't cast my
extendedTextBox as a 'BaseExtendedControl' to use the extension
methods, as the extendedTextBox inherits from the standard TextBox
class like this:
public class ExtendedTextBox : TextBox, IExtendedControl
so there's no common base to cast ExtendedTextBox as
'BaseExtendedControl' as it doesn't inherit from it.
Yes, you're right there is no common class, but you can solve the problem by casting to the IExtentedControl
interface which is common to your classes and contains the methods that you need. So what about:
public static class ExtendedControlHelper
{
public static void AddRequiredFieldValidator(this IExtendedControl control)
{
control.rfv = new RequiredFieldValidator();
control.rfv.ErrorMessage = control.RequiredMessage;
ConfigureAndAddValidator(control, control.rfv);
}
public static void ConfigureAndAddValidator(this IExtendedControl control, BaseValidator validator)
{
validator.ControlToValidate = control.ID;
validator.Display = ValidatorDisplay.Dynamic;
validator.CssClass = "validationMessage ";
validator.CssClass += control.ValidatorCssClass;
validator.EnableClientScript = control.ClientScript;
control.Controls.Add(validator);
}
}
I don't think you need to implement the IExtendedControl
interface in the ExtendedControlHelper
class. Moreover I corrected the grammar of the interface name from IExtendendControl
to IExtendedControl
.
EDIT :
Another solution could be to use the dynamic
keyword. The dynamic keyword is like object
but the type is checked at run time instead of compile time:
public static class ExtendedControlHelper
{
public static void AddRequiredFieldValidator(this dynamic control)
{
//...
}
public static void ConfigureAndAddValidator(this dynamic control, BaseValidator validator)
{
//...
}
}
The dynamic type doesn't exist at run time because it's solved by the compiler, so if you write this: myExtendedTextBox.AddRequiredFieldValidator();
the method is solved as
//...
public static void AddRequiredFieldValidator(this ExtendedTextBox control)
{
//...
}
and so on. So the type can change continuously at run time.
For more informations give a look here.
Completely ignoring any temptation to guess at the specifics of what you're trying to accomplish with your controls, or why, let me take a quick stab at answering your basic questions.
Up front; from your description, I think it sounds like your best option is just to have an instance field, not a static one, and not a singleton. You said "I actually need each instance of the control to have one such variable, not one variable across all the instances of the control in that single form." That is kind of a loose definition of an instance variable. Does it even really need to be public?
Actually, I would make it an instance property, because chances are pretty good that sooner or later you'll want to raise some event when the thing changes, or do something else that will end up making a public field feel like an unfortunate decision in retrospect. Hindsight is always 20/20. Or at least 20/30 or so. But in this case, a little foresight says that using a simple automatic property is cheap insurance:
public SomeDataType WidgetSettings{ get; set; }
So; there is only one instance of a static field/variable for the entire assembly. Every instance of the class containing that public static variable has a reference to the very same object in memory. So yes, all of your control instances are accessing the very same object/memory.
Any time you see "static" and "public" together in the same variable declaration line, it should be reason to pause and think. The thing is, if the variable is something like a string, or a numeric type, or a simple collection, you will have to use synchronization code everyplace that you access that field from. On the other hand, if it's a reference to a class with static getters and setters for various attributes, then you can put that synchronization code in the getters and setters, and you can test that class and its attributes in isolation (as a unit) and know that it works properly. I don't know if I expressed that as well as I meant to... But honestly, if you can what you need to do using instance variables and avoiding the whole thread-safety issue altogether, then do that instead.
If you have a static variable, it is absolutely for certain not thread-safe. At all. Maybe you're thinking that you're doing a Winforms app and all of the UI stuff executes on a single thread (because Winforms is not thread-safe), which is true enough if you follow the rules, except that we're all creative about using timers and background workers and such to loosen things up. So it is still possible for strange things to happen. So in the worst case, not only are all of your control instances accessing and updating the same variable, they might be trampling all over each other in the process.
If you're messing with WPF, then the UI library is thread-safe and the potential pitfalls of multithreading combined with static fields apply.
If the data that the variable points at is a type that requires more than one instruction to write completely, then it is only a matter of time before one control instance writes only half of a new value before the next control instance reads that field and gets a value composed of half of one write and half of a different write. I think the proper technical term for that situation is something along the lines of "fubar." Of course the thread that reads that mangled variable may well try to write back to it before it gets swapped out by the thread scheduler and the original thread gets another go, replacing the first thread's half-value with its own half-value before the first thread even gets a chance to write the second half of its value. This is likely to end in tears, or baldness, or more likely both tears and baldness.
Finally, the singleton has all the same potential thread-safety issues as the static field, because the whole notion of a singleton is that you grab your instance from a factory method, which serves the same single instance up to everybody who asks. So everybody who asks is, by definition, accessing the very same object.
In this case, my gut tells me that "singleton" is a code word for "fancy static field, which requires a lot more code and a lot more testing, and still isn't thread-safe unless you write error-prone and performance-robbing synchronization code to go with it."
When a code word has a definition that long, it's worth seriously looking at a different approach.
For what it's worth. :-) Without more detail it would be awfully difficult to provide any answers that relate directly to your question. What type of object is this static field pointing at? Is it a collection? Is it some kind of settings or configuration class with multiple properties? Is it an object that communicates with other parts of the system (events) in response to different signals you send it? Etc.
Best Answer
If you ran the aspnet_regsql.exe that should give you a great start and you wont need to re-invent the wheel (at least to get started). It implements the default Membership provider and gives you a lot of "off the shelf" functionality, which is what you're describing.. user login, remember password, attribute driven authentication (for MVC), directory level permissioning, and configuration based login redirects, session timeouts etc..
The aspnet_regsql tool gives you an empty database schema and makes it super easy to tie the default membership behavior into your own app including; Role based folder access, multiple applications with single sign on support, and some other membership / profile type tables (i generally dont use them much)).
You can also manage users / roles from Visual Studio using the website configuration tools from the web based management website.. and this is all built in and available without any additional coding / plug-ins.. i highly recommend it for new apps since it gives you so much in so little time and lets you focus on the fun part (the app)..
Also, you can carve down what's generated from there, or use it as an example. I usually just tie in their User_ID into the user of my schema and put a trigger or "on user created" event to sync the GUID's. That way i can get a user login, retreive password, and remember me up and running in about 10 minutes (it also handles situations where cookies aren't enabled).. and if there is ever a need to implement a custom provider, you can circle back, but at least the underlying functionality doesnt stop the app development from moving forward.
some info about aspnet_regsql.exe from MS:
http://msdn.microsoft.com/en-us/library/ms229862(v=vs.100).aspx
Here's a much better walkthrough:
http://weblogs.asp.net/sreejukg/archive/2011/06/16/usage-of-aspnet-regsql-exe-in-asp-net-4.aspx