Extending a class with a new nested class - c#

first question so I'm open to advice on effectively participating in the StackOverflow community as well as pertaining to the question.
I'm working on a text-based UI in C#. I have an abstract window class and an abstract control class, each of which implements common functionality for the types that inherit them (e.g. pop-up windows or text box controls). Currently, within a program that might implement the library, a developer would have to create window objects and control objects, and then add the controls to their respective windows, and the windows to a window manager class, like this:
var mainWindow = new MainWindow(...);
var textBox1 = new TextBox(...);
mainWindow.AddControl(textBox1);
WindowManager.Add(mainWindow);
This works, but it's a bit clunky. Since a control should never have to exist outside of a window, I was hoping to implement the control types as nested types. However, to maintain extensibility of the program, I'd like for there to be a way to extend the window class with new control types. My question is this: Should I use reflection, or rely on developers using container classes to extend the window class? Alternatively, is there a better way to structure the program than how it's currently laid out?
I've also considered using generics, e.g.:
public abstract class Window : DrawableObject, IWindow
{
public void AddControl <T>(object[] constructorArgs) where T : class, IControl
{
}
}
I'm aiming for ease of implementation without sacrificing extensibility/loose coupling. Thanks in advance for any thoughts!
EDIT: Should clarify, the primary reason for this is to fix some weirdness with how Windows and Controls cooperate. Each control has a parentWindow property which is used to access the window on which a control resides, for various purposes like creating an exit button for a particular window, etc.
Right now, this property is passed to the constructor, but that seems redundant to me since after doing so you have to add the control to the window's control list. I'd like to find a way to set this property when the control is added to a window instead, but restrict this action to when the control is added only, to prevent potential problems if the parentWindow property is changed outside of this context.

The way you coded AddControl method:
public void AddControl <T>(object[] constructorArgs)
where T : class, IControl
{
}
You intend developers to just provide type and your AddControl method will create an instance of it using constructorArgs. This method itself implicitly forces you to use reflection. Anything else does not stand a chance. Because To Add control of type T, Creating Instance of Control of type T is necessary. Since your Window class does not have a clue about T reflection is the only solution.
To facilitate other approaches, you might want to consider few overloads of AddControl.
public virtual T AddControl <T>()
where T : class, new(),IControl
{
//now you can create instance no reflection required
var control = new T();
this.Controls.Add(control);
return control;
}
public void AddControl <T>(T control)
where T : class, IControl
{
}
public abstract void AddControl <T>(object[] constructorArgs)
where T : class, IControl;
Creating an abstract method passes onus of implementation on child class and creating new instance of T can be handled the assuming type of T is known there or at-least all cases of known types of what T might be are handled.
It's a wide scope topic and I guess subjective as well. The best use of OOP is to achieve a design which fits your logical objective whatever that maybe.

Related

How to share a derived member variable with the base class

I'm using Xamarin to make an Android and iOS app. I have my code split into 3 projects: Android, iOS and common. The code is basically designed such that common code is abstract and handles the the OS agnostic side of things and the Android/iOS code inherits from the common and handles the OS specific things. However, I'm tripping over how to handle custom member variables following this paradigm, as I need to hold onto a OS specific instance so that the class can do OS things, but I also need to reference the OS specific instance in the common code to commonly handle things.
Example: A common class is comprised of a question and a chart (think public survey where you can see how other people responded). The common version of these things are responsible for retrieving their data from the appropriate places (database, server). The OS specific version of these things are responsible for displaying the UI. I would like to pass into this class the Android version of the question and chart. Then I can call the class' "retrieveData" (common) function and the class' "displayUi" (OS specific function). I would really like to reference the same member variables during this process.
If I program it 'normally', the common class would contain the common class of question and chart and the inherited Android class would access this variables. But this doesn't work because when the Android class access them, it gets the variables as common and doesn't have the OS specific functionality. If I put the variables in the Android class, then the base class doesn't know about them and I can't do common things with them.
Up to this point, I've gotten around this by using Generics. But I've recently ran into a problem with that solution (Inheriting generic can't up cast). Another solution I've thought of is using the 'new' operator on a property in the Android class to mask the inherited member variable and use the get function to automatically down cast the variable into the Android version and the set function to store the variable on the base (base.variable = value). I'm not too keen on this idea as I have to double declare the variables and I have a slight problem with collections of variables (I can either use Array.Convert (or some similar method) if I need to pass in the array/list/dictionary/etc, or I can cast as I iterate though it to do whatever it is I have to do. Not great, but doable.
I'm curious if there's other ways to to handle this situation .
Edit
Here's some simplified code:
public interface IAnsweredCommon { ... }
public interface IAnsweredAndroid : IAnsweredCommon { ... }
public abstract class ConstructorCommon<AnsweredType> where AnsweredType : IAnsweredCommon
{
protected AnsweredType Answered;
...
}
public class ConstructorAndroid : ConstructorCommon<IAnsweredAndroid> { ... }
As you can see, this version is using the generic pattern. ConstructorCommon has a variable of type AnsweredType which is treated as IAnsweredCommon within the class allowing it to do non-OS specific things with it. ConstructorAndroid inherits from ConstructorCommon using IAnsweredAndroid. This allows me to instantiate ConstructorAndroid without having to specify a type and allows it to treat the inherited AnsweredType as a IAnsweredAndroid to do OS specific things.
As mentioned in the previous question; this generic way won't work for an unrelated reason. So, to make code work in that question, I need away to replicate what the generic is doing. The only other way I can think of, is to change the Answered variable type from AnsweredType to IAnsweredCommon and to implement a new property in ConstructorAndroid that hides the Answered variable (via the 'new' keyword) and implement the get to return a casted base variable and set to set the base variable:
public abstract class ConstructorCommon
{
protected IAnsweredCommon Answered;
...
}
public class ConstructorAndroid : ConstructorCommon
{
protected new IAnsweredAndroid Answered
{
get => (IAnsweredAndroid)base.Answered;
set => base.Answered = value;
}
...
}
I'm not super crazy about this idea for the reasons I stated above, so I'm curious if there's another way.

C# WPF application: What is "this"?

I have been playing a lot with WPF applications in C# and there are a lot of things that are not really clear to me, I have been trying to look it up and play around with it to figure it out but without much success since english is my second tongue and I am still not that good with terminology nor with programming...
1: What is "this" in the main class? When I create the new WPF application in XAML I get window and a grid. However, I dislike XAML greatly and like to write code for all the elements and objects that I need so I delete that first grid, make a class, define my grid and to add it I have to write something like
this.AddChild(myGrid);
which is fine, but if I want to use "this" from my main class in other classes, it becomes a bit complicated to me. So, which UIElement or Object is "this"? How do I define it so it can be used in methods? "this", I suppose refers to the Window that is created at beginning, but what UIElement or Object is that Window?
2: Extended classes?? I have been watching a lot of java tutorials lately, simply to learn more about programming. There, to use the objects from other class you can simply write:
public class class1 extends class2{}
and everything is perfect, I have found out that I can mimic that same thing in C# WPF unless it's the main class, since main class extends :Window and I guess since it's defined as partial class... Is there a way to "extend" multiple classes or go around this?
Any help on clearing this up would be great :)
You should learn Object Oriented Programming in C#
this means the current instance of the class. So in each class this refers to a different object. this can usually be omitted and just AddChild(myGrid) can be used.
extends (or : in C#) means that the first class (class1) inherits from the second (class2) thus having access to methods and variables that are defined in class2 that are not marked private.
For the part about 'this' and its identity, the Window sits in a hierarchy of classes and can assume the identity of any of its ancestors. For example...
public MainWindow()
{
InitializeComponent();
var contentControl = this as ContentControl;
var control = this as Control;
var frameworkElement = this as FrameworkElement;
var uiElement = this as UIElement;
var dependencyObject = this as DependencyObject;
var dispatcher = this as DispatcherObject;
}
...all of the assignments in this snippet are legal. Also, there are more exotic assignments such as
var x = this as IInputElement;
The key here is to examine the framework and the various assignments available to each class. As others have pointed out, offline reading is essential to a quick learning curve.
The etymology of 'this' as a keyword in an object oriented context extends back to the late 1970's when it first appeared in an early specification for C++.
Finally, Xaml is one of the most attractive features of WPF for lots of reasons, and if Xaml isn't compatible with your approach, you MIGHT be better off in WinForms or Swing or similar tightly bound framework.
Simply said this is the class you are in.
For an example
class dim
{
int sum = 0;
public void num(int sum){
this.sum = sum; //Places the sum from num to the sum in dim
}
}
Extending a class is basically termed as Inheritance in Object Oriented Programming. There are several types of inheritance like single,multiple,multi-level,hierarchial,hybrid.But C# and also Java doesn't support inhertance from more than one class, because multiple inheritance creates a lot of ambiguity.
A feature that replaces multiple inheritance is the use of interfaces. Instead of 'extending from a class' we 'implement an interface' using the keyword 'implements'.An interface is just a skeleton class where you declare method signatures and the interface will be implemented in the class where you 'implement the interface'.The important point is you can implement more than one interface
To get an overview about Inheritance and Interfaces,the following link would be helpful:
http://msdn.microsoft.com/en-us/library/ms228387(v=vs.80).aspx

C# - Marking base class of custom Form makes Design View display HTML

Alright so. I have an app with several dialogs that have a handful of events that they all respond the same way to, and all have a few methods they provide to the Presenter. These have all been pushed up into a:
public abstract class BaseFormClass : Form
and all the other forms are:
public class DerivedFormClass : BaseFormClass
I've got a model-view-presenter setup going, so the base class has a few protected EventHandler<EventArgs>, and for each one is a similarly named function which is assigned to be called for that event, and a setter exists that the presenter can assign it's own function to be used as the handler for the event. (In other words:)
protected void OnFormBeginClosing(object sender, FormClosingEventArgs e)
{
if (formClosing == null)
return;
formClosing(sender, e);
}
public EventHandler OnFormClose
{
set
{
formClosing = value;
}
}
protected EventHander<EventArgs> formClosing;
Then the presenter uses the OnFormClose setter to set it's own handler function to handle any necessary cleanups or whatever's necessary.
Now that the backstory is out of the way, the main question is, why when I make the simple change of marking the parent Form as abstract does my design view of my child Forms go from the normal design view to just spitting out a mess of HTML (well, not a mess, a single line of what appears to be the entire HTML of the form...)?
Can anyone suggest what I might be doing wrong?
I have never tried this before, but trying the same in Visual Studio 2010, I get the error The designer must create an instance of type 'WinFormsTestApp.FormA' but it cannot because the type is declared as abstract.
I suspect this means exactly what it says - in order to display your derived form, for some reason known only to itself, the designer needs to create an instance of the parent form, and obviously can't do that. Sorry, but you will probably have to redesign your hierarchy. The VS designers make a lot of assumptions about the inheritance patterns used for forms and controls, so if you stray from the standard patterns, these problems are quite common.

Fix embedded resources for a generic UserControl

During a refactoring, I added a generic type parameter to MyControl, a class derived from UserControl. So my class is now MyControl<T>.
Now I get an error at runtime stating that the embedded resource file MyControl`1.resources cannot be found. A quick look with .NET Reflector shows that the resource file is actually called MyControl.resources, without the `1.
At the start of the MyControl<T>.InitializeComponent method there is this line which is probably the one causing problems:
System.ComponentModel.ComponentResourceManager resources =
new System.ComponentModel.ComponentResourceManager(
typeof(MyControl<>));
How do I force the ComponentResourceManager to use the embedded resource file MyControl.resources? Other ways to resolve this issue are also welcome.
Turns out you can override the resource filename to load by inheriting from ComponentResourceManager like this:
using System;
using System.ComponentModel;
internal class CustomComponentResourceManager : ComponentResourceManager
{
public CustomComponentResourceManager(Type type, string resourceName)
: base(type)
{
this.BaseNameField = resourceName;
}
}
Now I can make sure that the resource manager loads MyControl.resources like this:
System.ComponentModel.ComponentResourceManager resources =
new CustomComponentResourceManager(typeof(MyControl<>), "MyControl");
This seems to work.
edit: the above line is overwritten if you use the designer, because it is in the
generated code region. I avoid the designer and make use of version control tools to revert any unwanted changes, but the solution is not ideal.
In addition to Wim's technique, you can also declare a non-generic base control that has the same name as your generic class, and have your generic control/form derive from that non-generic base class.
This way you can trick both the designer and the compiler into using the resource file from your generic class, and you get permanent designer support once the base class is setup without having to fiddle in the .designer file everytime you rebuild :
// Empty stub class, must be in a different file (added as a new class, not UserControl
// or Form template)
public class MyControl : UserControl
{
}
// Generic class
public class MyControl<T> : MyControl
{
// ...
}
The only requirements are to have exactly the same name for your generic class and its base class, and that the base class must be in another class file, otherwise the designer complains about not finding one of the two classes.
PS. I tested this with forms, but it should work the same with controls.
On my Visual Studio 2008 I have this error:
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MyControl));
Using the generic type 'WindowsFormsApplication1.UserControl1' requires '1' type arguments.
Notice that in my case code was generated without parentheses, <>, after the class name.
It is becoming interesting, see ImageList autogenerates non-compiling code in a Generic User Control.
What they said:
Posted by Microsoft on 7/6/2005 at 2:49 PM
This is an interesting bug. You've hit upon a generic scneario that we do not support in the Windows Forms designer. We will not be able to add support for this in the Whidbey (my note: Visual Studio 2008?) release. We will consider this for a future version. As a workaround, you can use the designer to create a none generic UserControl with a public Type property and then create a generic class that inherits from it and passes T into the base classes Type property.
I suppose this control cannot be designed in the Visual Studio forms designer either.
The simplest and easiest workaround is to make a dummy class for the autogenerated typeof(). You do not need to inherit from it or even expose it to the outside:
// Non-generic name so that autogenerated resource loading code is happy
internal sealed class GridEditorForm
{
}
(In my experience, the time required getting the designer to work around generics was not worth the ideal coolness generics can provide. I won't be using generic windows forms or controls again.)

Passing objects to a UITypeEditor

I am currently hoping to use a PropertyGrid to allow users to edit some of my classes, however I've hit a wall with passing objects to the UITypeEditor(s) they use. When the user presses the drop down I want to show a listbox of already loaded textures to choose from, if they want to use a texture the application hasn't loaded yet they can click a button to choose one from a file dialog. In case I make no sense here a mock of the form:
.
My problem: To fill the listbox I need access to the class that manages the list of resources from the UITypeEditor.
Now I've solved this problem for my own classes by giving them a reference on creation to their managing object. In the UITypeEditor I then use that reference to access what I need. However I can't do this for classes I haven't written, such as the XNA Texture2D class.
Here are what the classes I'm using look like:
class StaticGeometryChunk
{
// Geometry data to draw with. Contains a reference to its managing
// class for use in its UITypeEditor.
public GeometryData { get; set; }
....
}
class Material
{
// These are XNA classes. I can't just add a reference to its managing
// class (I think?).
public Texture2D Texture1 { get; set; }
public Texture2D Texture2 { get; set; }
....
}
I've been looking at my options and they seem to be:
Make the managing classes static.
I don't really want to do this. There are several managing classes as each resource is loaded differently. There are also classes that need to be created before these and are passed in.
Make the managing classes singletons.
I don't really want to do this either. It seems like a quick and dirty way to "hide" the problem instead of "solve" it. I also might want the option of having several managing classes in the future which the singletons eliminate.
Create a wrapper class which holds the reference to a managing class and its target (such as the XNA Texture2D).
This is currently what I'm thinking of doing. Its would be quite simple and quick to do but something about it nags me but I don't know what.
Any thoughts on the above or other methods to pass what I need into the UITypeEditor?
Thank you for reading.
In the EditValue method, you are given a context. Use context.Instance to access the object that holds your property. This object should also contain a property that gives you access to the list of things you want to display. You could test if context.Instance is ITextureProvider for example, then cast it and access the textures. Not sure if this makes sense in your design but let me know.
As an alternative you can try the following approach. I find it very elegant, because it does not require to store a list of available property values in the object. Therefore, for example, you can show one set of values on one form and another set on another.
Create an interface IYourDataProviderService.
Create an implementation of IYourDataProviderService, which knows the concrete data to provide.
Create a class implementing ISite. In GetService() method return an instance of class which implements IYourDataProviderService, if the serviceType parameter is typeof(IYourDataProviderService).
I left rest of ISite methods throwing NotImplementedException (except DesignMode property) and for me it worked, but probably this is not an ideal solution.
In 'Load' event handler assign your implementation to the Site property of your propertygrid.
Enjoy!

Categories