Currently I'm working in a tool that needs to create some sort of customized .NET with some additional fields. I've been wondering what approach is better to solve this, and been thinking in the following options:
Option A:
- Create a derived class for each control (let's say, CLabel, CGroupBox...) where I define the new fields on each class. This would mean worse mantainability but would be easy to operate with.
Example:
class CLabel: Label
{
public List<Control> RelatedControls {get; set;}
public String textHint;
// more stuff...
public CLabel()
{}
}
Option B:
- This option would mean not creating a derived class from each control, but using the actual Label, GroupBox, etc controls and creating a class encapsulating all the "extra" properties. This extra properties object would be referenced in the Control.Tag property. I have doubts about this one because referencing a sort of complex object inside the Tag property feels a bit crappy to me, but this would mean better mantainability and also of course no need of subclassing controls.
Example:
Label lbl = new Label();
lbl.Tag = new ControlDescription();
Option C:
- This would mean having some sort of combination of Option A and B. Just creating the Custom Control, for example CLabel, that adds a type ControlDescription field to the Label control. This way we ensure encapsulation and mantainability, but we avoid the Tag thing.
I'm pretty sure there are lots of options out there better than those. Probably just using polymorphism - a concept I still have problems with - the custom control classes could be taken away. What of those options do you think is the best one? Do you think that all of this could be better done?
If you need easy control of the properties at design-time and you must go with windows forms you should have a lock at this http://msdn.microsoft.com/en-us/library/system.componentmodel.iextenderprovider.aspx
This way you can provide properties to different controls without wrapping them first controls.
If I correctly understand you, I'd prefer to use extension methods here. If you need to store some custom values for each control - you can store them in the static dictionary (Control, Value) but use extension methods to access it, so it would look like you have controls with some values added.
Added an example:
public static class Extension
{
private static Dictionary<Control, string> _controlStrings;
public static void GetString(this Control ctrl)
{
return _controlStrings[ctrl];
}
}
After that you can use this method like:
Button btn = new Button();
string s = btn.GetString();
Probably you could try this:
public class ExtensionData
{
//put your data here
}
public class Extended<T>
where T : Control
{
public Extended( T baseControl )
{
BaseControl = baseControl;
}
public T BaseControl { get; set; }
public ExtensionData Extension { get; set; }
}
It's like your "option B", but without using "Tag" property
Related
Here's the code I have:
public class BaseButtonSheet : PopupBase
{
public BaseButtonSheet()
{
BindingContext = new BaseButtonSheetViewModel();
contentStack.Children.Add(new PopupHeaderLabel("Screen Options"));
grid.Children.Add(new BaseButton("Add Deck", "AddCmd"), 0, 0);
contentStack.Children.Add(grid);
}
}
public class PopupBase : Rg.Plugins.Popup.Pages.PopupPage
{
public StackLayout contentStack;
public Grid grid;
public PopupBase()
{
What I am unsure of is if it's more common and if there is an advantage to create contentStack and grid as properties because I will be accessing them from a different class.
Because they are public I would use properties.
See this:
Generally, you should use fields only for variables that have private or protected accessibility. Data that your class exposes to client code should be provided through methods, properties, and indexers
C# programming guide, Microsoft
As well as the advice from Microsoft, there are advantages to wrapping access to variable in properties.
You can change the way a property is implemented in an inheriting class.
e.g. You could have an AdvancedButtonSheet, and redefine how the contentStack property is retrieved, providing additional benefit for your advanced buttons, just by calling the "same" property.
I have a library (no source), to an certain object of which, I need to add some properties.
What would be the a way to do it ? I'm aware I could extend the class and add properties to the child. As well I know there are NO Extension Properties in C# yet. What would you suggest ? Thank you !
The metadata of class could be something like :
public class ResultClass
{
public IList<Item> Results { get; set; }
public int TotalResults { get; set; }
}
and I want to add a :
String description;
to it. Thanks.
There are a couple strategies you could take. Inheritance is the most obvious one. You might also consider composition. Can you give us some more details about what the object is and what properties you need to add to it and why?
After seeing the expanded question:
Either strategy outlined above (composition or inheritance) will probably work for you. Personally, I prefer composition. I think it better insulates you from changes that might be made to the third party library. It also forces you to work through the public interface of the library class, which is preferable when you have no knowledge or control of the internals of a class.
Here is the most basic example of composition.
public CompositeClass
{
private ResultClass _resultClass = new ResultClass();
public IList<Item> Results
{
get { return _resultClass.Results; }
set { _resultClass.Results = value; }
}
public int TotalResults
{
get { return _resultClass.TotalResults; }
set { _resultClass.TotalResults = value; }
}
//
// New Property
//
public string Description { get; set; }
}
Why do you need to add properties? If this is for binding purposes then I would suggest creating a wrapper class or creating your own inherited type that can raise PropertyChanged events in response to various state changes in your third party types. Instead of telling us your proposed solution you should tell us the actual problem you are trying to solve. Also (as I can't vote to close/migrate), this is not really a valid discussion for this site.
I think you are mixing up Extension Methods with Extension Properties.
And the last ones do not exist in C#.
So you should extend the class or create an inheriting class.
First thing to note - I KNOW DELEGATION AND DECORATOR PATTERNS!
Second - I am using C# .NET 4.0, so if you come up with a solution that is specific for it, that's fine. But if solution will work for any OOP language and platform, that would be great.
And here the question goes...
I have a partial class (lets name it Class1), which I cannot modify. Thus, I can just extend it or/and inherit from it. This class provides a perfect data model for me, the only thing I need is to add some attributes to its properties (for validation, defining label text value in MVC etc - for now, I do not need answers like 'you can do what you need without attributes', that's not the matter of my question).
It is not a problem to use another class as a data model, so I can, say, create Class2 : Class1 and use Class2 as a model. Properties that need attributes would be defined as public new <type> <propertyname>. This will limit me to rewriting only the properties that need attributes, leaving all other untouched.
The smaller problem is that I do not what to redefine getters and setters for the properties, as all they gonna contain is return base.<propertyname> and base.<propertyname> = value, and if there are lots of such properties, this means lots of "stupid" coding. Is there a way to avoid this?
The bigger problem is that I have to parametrize my Class2 with Class1 instance and make something like class2.<propertyname> = class1.<propertyname> for each single property I have - too much of "stupid" coding. I can avoid it using reflection - find all properties with public getters and setters in Class1 and call prop.SetValue(child, prop.GetValue(parent, null), null); in the loop. This provides a generic function for simple cases, which is quite fine, as I mostly have simple models - lots of properties with public getters and setters without body and another logic. But I want more generic solution, and I do not like reflection. Any ideas?
Here goes the full code of the extension method that creates Class2 basing on Class1
public static Child ToExtendedChild<Parent, Child>(this Parent parent)
where Child : Parent, new()
{
Child child = new Child();
var props = typeof(Parent).GetProperties().Where(p => p.GetAccessors().Count() >= 2);
foreach (var prop in props)
{
prop.SetValue(child, prop.GetValue(parent, null), null);
}
return child;
}
(by the way, this method may not ideally implement my solution, so any corrections would also be appreciated)
Thanks in advance!
The smaller problem doesn't seem to be much of a problem. Maybe I'm misunderstanding the question, but assuming you're simply deriving a subclass, there should be no reason to redefine either the properties or their associated getters/setters.
The bigger problem might be resolved using something a little simpler. Using reflection for a lot of your object initialization seems a little expensive. If you're dealing with a class that is primarily a big bag or properties, maybe you should as if you need access to all of those properties in any given situation. You mention MVC and validation, is the entire model being used in the controller method you're validation is taking place in? If not, why not look at using a viewmodel that only exposes those pieces you need in that method?
Your reflection initializer is interesting, but if you're going to be doing a lot of this then you might consider investing a little time with Automapper. Otherwise maybe consider moving away from a generic solution to something that just tackles the problem at hand, i.e. mapping properties from an instance of an object to another instance of a derived object. Maybe you can create a copy constructor in the parent class and use that in your derived class?
public class Foo {
public string PropOne { get; set; }
public string PropTwo { get; set; }
public Foo(string propOne, string propTwo) {
PropOne = propOne;
PropTwo = propTwo;
}
public Foo(Foo foo) {
PropOne = foo.PropOne;
PropTwo = foo.PropTwo;
}
}
public class Pho : Foo {
// if you have additional properties then handle them here
// and let the base class take care of the rest.
public string PropThree { get; set; }
public Pho(string propOne, string propTwo, string propThree)
: base(propOne, propTwo) {
PropThree = propThree;
}
public Pho(Pho pho) : base(pho) {
PropThree = pho.PropThree;
}
// otherwise you can just rely on a copy constructor
// to handle the initialization.
public Pho(Foo foo) : base(foo) {}
}
I assume the partial class is generated code, it makes the most sense given your scenario.
I know of one way to do this, but depending on how the attribute gets crawled, it may not work.
// Generated Code
public partial Class1
{
public string Foo { get { ... } }
}
// Your Code
public interface IClass1
{
[MyAttribute]
public string Foo { get; }
}
public partial Class1 : IClass1
{
}
If someone were to look at attributes by using GetCustomAttributes with inheritance, then I think they would get this attribute.
As an aside, whenever I see generated code that doesn't have virtual properties it makes me cry a little bit inside.
To address your bigger question, why don't you just make Class2 a wrapper for Class1. Instead of copying all of the properties you can just give Class2 an instance of Class1 in the constructor, store it locally and make all of your properties pass-throughs. It means some hand coding, but if you're building a Class2 by hand anyway and want to decorate it with a bunch of attributes, well, you're hand coding Class2 anyway.
I have different sets of custom Winforms controls all deriving from Control such as:
CalculatorPanel, GraphPanel, DisplayPanel, etc : Control
I use a single Form to display one or more of these sets depending on what the user wants to see.
All of them has a member called:
Input
where the type is different such as:
CalculatorInput, GraphInput, DisplayInput, etc.
How do I store them in a list or some other collection where I can call the Input property without any problem?
Should I use a common interface for each? Then it has to be generic. How will I specify the type?
Right now I use something like this to add/remove controls:
Panels = Dictionary <Enum, Control> ...
Panels.Add (PanelType.Calculator, new CalculatorInput ().Controls);
...
so later I can say:
Form.Add/RemoveControls (Panels[PanelType.Calculator])
but how would I set their Input property when I need to at runtime. So if the user switches to the GraphPanel, I want to be able to set it's Input right after I added its controls to the Form.
Is there a design pattern or a technique to solve this?
EDIT: Properties of each input type (no methods) are as follows:
CalculatorInput:
.Result
.LastOperation
...
GraphInput:
.Result
.SelectedNode
...
DisplayInput:
.Result
.CurrentColor
...
Basically these inputs are just types to be bound to the appropriate UI. So if the UI has some properties, they are bound to these input, which is why when I assign a new input, the UI will update automatically.
EDIT2:
So all these inputs are separate no inheritance, etc.
But are defined in appropriate rollouts as follows:
class CalculatorPanel
{
CalculatorInput Input
}
class GraphPanel
{
GraphInput Input
}
class DisplayPanel
{
DisplayInput Input
}
I think what you need is an INTERFACE for your Input that all classes will inherit from..
public interface MyInputInterface
{
void YourInputFunction();
}
public class CalculatorPanel : Control, MyInputInterface
{
..
..
void MyInputInterface.YourInputFunction()
{
// do your code specific to calculator panel here
}
}
public class GraphPanel : Control, MyInputInterface
{
..
..
void MyInputInterface.YourInputFunction()
{
// do your code specific to graph panel here
}
}
Then, you can build a list of anything that implements MyInputInterface
public List<MyInputInterface> MyInputList = new List<MyInputInterface>();
and work with that list as needed... The Interface is a contract of any object utilizing it to guarantee it has the associated properties, fields, functions, etc.
Since the inputs are essentially separate, they could implement an interface for the small amount of common functionality, but it probably wouldn't accomplish much (it would help to know the data types of the input class members). To get access to the non-common functionality (which is most of the input objects), you'll still need extra logic to get things working:
if (currentControl is CalculatorPanel)
{
CalculatorInput input = (currentControl as CalculatorPanel).Input;
// ...
}
else if (currentControl is GraphPanel)
{
}
etc.
I have a bunch of MDI child nodes that are all created in the same way and to reduce redundant code I'd like to be able to call a method, pass it a string (name of child node), have it create the node and add it to the parent.
I can do all the stuff except create the class from a string of a class name, how can I do this?
I'm currently using this in one of my applications to new up a class
public static IMobileAdapter CreateAdapter(Type AdapterType)
{
return (IMobileAdapter)System.Activator.CreateInstance(AdapterType);
}
It's returning an instance of a class that implements IMobileAdapter, but you could use it equally easily with a string:
public static IMyClassInterface CreateClass(string MyClassType)
{
return (IMyClassInterface)System.Activator.CreateInstance(Type.GetType(MyClassType));
}
Call it using code similar to the following:
IMyClassInterface myInst = CreateClass("MyNamespace.MyClass, MyAssembly");
Of course, the class it creates must implement the interface IMyClassInterface in this case, but with a class factory, you'd likely have all your classes implementing the same interface anyway.
Edit:
In reference to your comment, for the purpose of this discussion, think of the term "assembly" as the set of files within your vb/cs project. I'm assuming that you're doing this all within a single project [assembly] and not spreading over multiple projects.
In your case as your classes will be extending the Form object, you would do something like this.
Form myInst = CreateClass("MyExtendedForm");
Or
Form myInst = CreateClass(Type.GetType("MyExtendedForm"));
Depending on whether you get the type within your CreateClass method or outside it. You would need to cast your instance to the correct type in order to access any custom members. Consider this:
class MyCustomForm : Form
{
public int myCustomField{ get; set; }
}
I've got a custom form that extends Form adding the myCustomField property. I want to instantiate this using Activator.CreateInstance():
public static Form CreateClass(string InstanceName)
{
return (Form)System.Activator.CreateInstance(Type.GetType(InstanceName));
}
I then call it using:
Form myInst = CreateClass("MyCustomForm");
So now I have my custom form stored in myInst. However, to access the custom property [myCustomField], you would need to cast your instance to the correct form:
int someVal = ((Type.GetType("MyCustomForm"))myInst).myCustomField;
Activator.CreateInstance(Type.GetType(typeName))
If you have a string which is the name of the class, then you should be able to get a Type object therefrom, by calling Type.GetType(string). From that type, you should be able to use reflection to generate an object.