How to represent (class) data for GUI generation? - c#

I'm trying to make a small application that can edit the data files from an earlier project. I have access to that projects "data classes" (pretty dumb classes whose main purpose is to expose it's (public) member variables) that can read/write to the files. All I have to do is make a GUI that can edit the different member variables that each data class have (preferably without modifying the data class) and I'm trying to figure out how to do this so that it will be easy to adapt for future changes/additions.
(I don't feel like I can assume that all member variables should be editable, might only be a selection of them).
All the data can be converted to/from strings (numbers and text) and I don't see much problem in generating textboxes and/or something like a DataGridView in the GUI, but I'm not sure as to how I would like to represent the data needed to generate those.
My first thought was to use a list with all variables for each data class. With each row in the list containing the name+description of the variable (for the GUI), a pointer to the variable in the data-class and perhaps some form of validation-function for different variables.
Store that list in a class that inherits the original data-class (and that implements an interface/abstract-class for any specific GUI-related functions (load/save etc.)).
The thing that makes me worry about this solution is just that I feel like this should be a somewhat common problem and I'm a bit rusty when it comes to OO and this solution smells like something I'd write if I had to do it in C.
There might even be a handy language construct, design pattern or something that is suitable but I don't know what to search for.
Does this approach even seem sensible?

Reflection is your friend in this case. Your data classes have a structure which can be explored using that class's Type. A Type is the base class for metadata concerning a class or structure, and includes methods to, for instance, get a list of all fields, properties and/or methods belonging to that class. The objects representing these class "members" can then be used to set or get field or property values, or invoke methods, given an instance of an object of that type.
A reflective algorithm can be designed to handle any object structure it is given, and it doesn't have to know those structures at compile-time unlike an algorithm based on static types. The downside? It's slow, and you get very little compile-time checking of your algorithm so it can fail at run-time in unexpected ways.
Here's something to get you started:
//statically set up an instance of some arbitrary object
MyClass myObject = new MyClass();
myObject.Field1 = "Hello";
myObject.Field2 = "World";
//This method is available on any object, and produces a Type representing the class definition
Type myType = myObject.GetType();
//C# also has a typeof() keyword that works when you have a static type and not an instance
myType = typeof(MyObject);
//Interrogate the Type instance to get its fields
FieldInfo[] fields = myType.GetFields();
//then, iterate through the fields to perform some (useful?) work.
//Here, we are outputting a list of paired field names and their current values.
//You will probably want to instantiate a Label and Textbox representing this value
//and show them on a Form.
foreach(FieldInfo field in fields)
Console.WriteLine(String.Format("{0}: {1}", field.Name, field.GetValue(myObject));
To handle editability, you will need some sort of record of what the user has permission to change and what they don't. If that information will never change from user to user, you can incorporate that information into the data class itself using attributes (which won't change the "interface" of the object; it'll still have all the same members, but those members will have additional metadata). You could also create another set of classes that implement an interface defining each one as a set of "field permissions" for its parent class, and then you can dynamically construct an instance of the "field permission" class with a Type instance representing your object definition, and knowledge of the name of the interface that field permission objects implement.

Related

Let class only contain value type fields

What I want to achieve:
A container which contains a bunches of value type fields.
The container has the following characteristics
Acts like POD.
Mutable
Could be copied by value.
Fields of the container will keep growing in the future.
For letting it could be copied, my attempt is using MemberwiseClone() which would shallow copy the container.
So a class containing only value type fields might work, but MemberwiseClone() could be broken once the class contains a reference type while MemberwiseClone() copy the reference.
My intent is to prevent inexperienced developers from accidentally breaking the system.
Expected answer:
Some kind of attribute node [AllowOnlyValueTypeFields] on a class to allow the compiler to check it.
[AllowOnlyValueTypeFields]
class foo {
int[] bar; // beep! compiled failed.
}
Maybe... a design pattern might solve it?
Current workaround:
A unit test using reflection and check every field of the container.
A "rule" about not using reference type in this container and soon become forgotten.
Search keywords:
C# field property only value type
C# field property allow only value type
C# force only value type field stackoverflow
None of the above got meaningful results.
Any suggestion is appreciated.

how is a tuple different from a class?

how is a tuple different from a class? instead of the following code, we can make a class with 3 fields and make objects from it. How is this Tuple different from that? Is it only reducing the code we write or does it have something to do with speed as well, given the fact that you can't change the items in a tuple.
Tuple<int, string, bool> tuple = new Tuple<int, string, bool>(1, "cat", true);
It saves you from having to define a new class with custom properties.
It does define equality by the value of the three items, which is something that a bare-bones class would not do without custom coding. That plus the fact that it's immutable makes it a reasonable candidate for a hash key in a Dictionary.
One drawback is that the properties are vanilla Item1, Item2, etc., so they don't provide any context to the values within them, where properties like ID, Name, Age would.
Tuple is a class. One that holds any data you want (in terribly named properties like Item1).
You should be making classes instead so your code is more readable/maintainable. Its primary function is as a "quick fix" when you want to associate pieces of data without making a class to hold them.
Tuples are in my opinion an invitation to bad data modeling. Instead of creating a proper model you get a generic object that can hold n item properties. The naming is very generic too.. Item1..ItemN
You use Tuples as a mean to pass data between method call without having to define a new class. Typically use to return multiple pieces of data from a method rather than use "out" parameters.
Keep in mind that out parameter cannot be use with async/await methods, this is where Tuples come in handy.
You probably want to define a class for your data if you code a reusable class library though. However, tuple is great in presentation layer.

How can I add a property to a class through inheritance and then cast the base class to the new class?

I'm wondering if there is a way to do this inheritance situation in C#:
public class Item
{
public string Name { get; set; }
}
public class ItemExtended : Item
{
public int ExtendedProp { get; set; }
}
And let's say I have a method that returns objects of type Item:
public Item[] GetItems();
How can I make code like this run?
ItemExtended[] itemsExt = GetItems().Cast(i => (ExtendedItem)i).ToArray();
Where the cast wouldn't fail, the Name property value would be preserved and I would have an additional property ExtendedProp that I could access?
Edit (hopefully to clear some confusion)
In this situation the GetItems method would only ever return items of type Item. I was wondering if there was a casting method that could convert a base type to an inherited type such that all base member values are conserved (without the use of cloning).
If the runtime type of your object is Item, you can not cast it to an ItemExtended -- not unless there's a user-defined conversion that can create an ItemExtended from an Item. Note, however, that even then, you'll be creating a new instance of ItemExtended.
Inheritance in general doesn't work that way. In managed languages, downcasting only works if the runtime type of your object already is of the derived type. Instances of derived classes inherit all the data and behavior of their ancestor classes, but there's an ancestor doesn't have any knowledge of derived classes. Consider an example, where a derived class introduces a single new field. Firstly, the base class instance is smaller in size, so at the very least, a type cast would require allocating new memory. Second, you would have to decide between changing the runtime type of the original instance (which would be very weird indeed) or making a copy of the old data. The latter way would be very similar to the user-defined conversion scenario, except an user-defined conversion is explicitly invoked, and IMO better that way.
In unmanaged languages, you can of course make any arbitrary conversion you want -- but that just results in catastrophic failures if you do it wrong. In the example above, you would try to access the new field, but since it would not have been allocated for the instance, you would go beyond the boundaries of the object's memory space and access... whatever was in there, be it sensical or not.
If you want to introduce new behavior to existing classes, the C# way is via extension methods. Extension properties aren't there yet, and may never be, so you don't get the property syntax. You may or may not be able to live with that.
You may also find it interesting, that in XAML, the concept of attached properties sort of fits what you are trying to do: you can define arbitrary new properties for whatever -- but if you look at the implementation, what you are really doing is creating a dictionary that maps objects to their associated property values, and the XAML compiler sugarcoats this by making the markup look like you've added the properties to those objects.
You can use OfType instead of Cast:
ItemExtended[] itemsExt = GetItems().OfType<ItemExtended>().ToArray();
You're on the right track with a few adjustments,
use Select() instead of Cast() and
i as ItemExtended rather than (ItemExtended)i
This line should cast it correctly:
ItemExtended[] itemsExt = GetItems().Select(i => i as ItemExtended).ToArray();

How to instantiate a subtype inside a dynamic class?

I'm using C# dynamic keyword and I've got an instance where I need to set a property value.
However, this property requires a type that I have no access to since I generated an assembly in memory from WSDL.
How can I create the property instance dynamically?
There is no such thing as a property instance; there is:
an instance of an object
which has members (which may be dynamic in this case)
to which you want to assign a value
If you don't know the type of the value in advance, you will need to create the object with a combination of reflection (from the Type) and perhaps dynamic. The latter depends on whether the underlying object is actually dynamic, vs being a regular type exposed via the dynamic API. Likewise, whether you can assign the value to the property via reflection - or whether you must use the dynamic API - depends on the same. Fortunately, there are tools like FastMember which allow you to access arbitrary members (with names known only at runtime, not compile-time) identically for the two cases. So if the scenario is complex, maybe give that a whirl.

Providing Inherited Static Properties (conceptually)

I have a C# base class that I was to associate information with on a per-type (rather than per-instance) basis. Essentially I want all child classes to present an Icon and a FriendlyName that represents the type. I'd like to not have to create a type instance to get this information and I want to require that all child classes provide this information. Ideally it would be in the interface that the base derives from.
I tried to use a class Attribute, but it requires a constant value, so while I can set the FriendlyName, I can't set the Icon, and I can't see a way to make the Attribute required anyway, so child classes could get away with not having it (until run time).
I added a static Property to the base that children can hide, but that's kind of ugly and the values from the base are really nonsensical. It can't know what the name would be for a child. I could have the base throw in the Property, but again, that wouldn't get caught until run time.
Anyone have any ideas on how I might implement something like this? Is there a pattern I'm missing? Any out-of-the-box thinking is encouraged as well.
Edit: Really what I need to the ability to require class Attributes along an inheritance tree and be able to use an embedded resource to set those attributes. All of the information that will be returned really is static and known at compile. I just can't figure out a way to nicely expose it.
Edit 2: Here's a more concrete example of what I need:
Let's assume I have a base class:
abstract class Vehicle { ... }
I then have two children:
class Car : Vehicle { ... }
class Truck : Vehicle { ... }
I'd like to be able to get an Icon representing a "Car" or a "Truck" without having to create an instance of one (a la Car.Icon) since all vehicles of a given type will all have the same icon.
I also want to ensure that all Vehicle-derived Types expose the same way to get this Icon in case someone comes along in the future and adds a new class
class Airplane : Vehicle { ... }
Edit 3: Why do I need this? Well we have an app that can take plug-ins. The plug in is defined by a type, and when the type is loaded, we show the user an icon and name. When they click the icon, it creates an instance of that type (and gives them a dialog for naming the instance, etc). I don't need or want to have to create an instance of the type to get the icon.
If you want to absolutely dictate that the child implement this, then the only way I see doing it is making the base class abstract, and expose instance properties to return the icon and friendly name.
These would be abstract, not virtual, so you force the implementation by the derived class. I know it's not clean, in that it is information that is better stored on the type level, but it's the only way I can see to enforce this requirement at compile-time.
I think the point you may have missed is that you can't override static properties for a good reason -- namely that when you're writing code to call it, you don't have an instace, so the complier will statically link it at that time -- if you need polymorphism, you need to be working with an instance for the runtime to work out which version of the method to call.
EDIT: (In response to your EDIT2)
What scenario would you want to be calling this from?
If you're wanting to show your icon against an instance, you've got an instance, so why not have it as a property on the instance (because, after all, somebody might override your Car to create a SportsCar and want a different icon for it) -- in effect you're asking for a property of your object, albeit one that matches the conceptual model (so it's not the number of wheels, the max speed, etc; but something to visualise it to the end user)
EDIT2: (In response to your EDIT3)
The approach I'd do would be something along the lines using an attribute to identify which embedded resource to use as the icon for the respective type (so you don't need an instance), and use reflection to read the value. You could define your own custom attribute, or look at ToolboxItemAttribute which might be of use.
Maybe what you can do is to define an attribute that will be used for registering that object in your plugin system.
This way you will enforce the developer of the class to assign the attribute in order to work within your plugin system.
Maybe you can use an approach like the ToolboxBitmapAttribute, where you can set an image found into a resource of your dll.

Categories