How would I create Dynamic Class Items? C# WinForms - c#

I want to dynamically add items to a class, but someone may have to help me with my syntax here.
I've got a ContainerTank class like this:
class ContainerTank {
double radius;
public ContainerTank(int diameter) {
radius = (double)diameter / 2;
}
public int Gauge {get;set;}
public double Volume { get { return (3.1415)*(radius*radius)*Gauge; } }
}
Each of our Sites can have anything from none to an absurd value of 10 tanks (water tanks, oil tanks, etc.).
I can easily create a Class that using List<ContainerTank> tankList to maintain the data in each tank per site, but I'd rather find a way to initialize my class by specifying how many tanks are on a site, then have each tank show up individually.
For example, if I create a new site with 2 tanks, I would have a map to Tank1 and Tank2 (or Tank0 and Tank1 if you want to use zero index).
Why?
For our developers using the code, seeing Tank1 and Tank2 pop up with Visual Studio's IntelliSense would help them when using our control rather than presenting them with a collection.
Mainly, I want to know if it can be done and how I'd implement it.

No, this isn't possible. All class members must be specified when the assembly is compiled.
If what you're interested in is purely ease of debugging, it's possible to write your own debug visualizer.

Related

Any way to get the definition of a property from the code itself?

public abstract class Unit
{
public abstract List<Move> allowedMoves{get;}
}
public class Javelineer : Unit
{
public List<Move> allowedMoves =>
new List<Move> {Move.Impale, Move.JavelinThrow, Move.ShieldBlock};
}
public class Dragon : Unit
{
public List<Move> allowedMoves =>
new List<Move> {Move.BreatheFire, Move.Swipe, Move.Bite, Move.Devour, Move.TailBash};
}
The X:
Given the above code, if and how can I retrieve the allowed moves of a given unit without necessarily instantiating a new object?
I know I can retrieve the property with this code:
typeof(Javelineer).GetProperty("allowedMoves")
But if and how can I retrieve the definition of this property?
The Y:
The client (web browser) must send the game server the player's unit. This includes the unit's type and moves this unit is able to perform (4 out of all available; similarily to Pokemon).
While the validation (of course) is performed on the server, the browser still needs to get a list of available unit types and allowed moves.
In order not to duplicate code, I would like to avoid hard-coding this data in Javascript.
Having read some excellent SO questions & answers I think I can retrieve all available units with code similar to this:
Assembly.GetExecutingAssembly().GetTypes().Where(
type => type.BaseType == typeof(Unit)
).Select(type => type.Name).ToList()
I'd call this code on server startup, cache the result and send the cached result to every connecting client, because I have feeling this code is likely expensive to call.
But how can I retrieve the list of allowed moves?
You have a couple of options, but TL;DR: Construct the object instance and read the property.
In any case, here are some options, creative minds might be able to find a couple more even.
Construct the instance, read the property.
This is your best option code-wise because it will be easy to understand, maintain, bugfix.
Rewrite the code to allow for easy detection of the values using reflection
One way to do this would be to use attributes, tagging the property or object with the legal moves. However, to avoid having the bug that the attributes does one thing, the code another, you might have to change the code to use the attributes as well, which would be a performance hit.
Additionally, reading those attributes would likely construct many more objects than your original object.
Use mono.cecil or some other IL-inspection library to decode the code of the property getter and finding the construction of that list, extracting the values being added to the list. You would essentially either have to dumb down the code of that property to be on par with what you have right now (and never allow it to become more complex) or basically simulate execution of code.
This is like constructing a flotilla of space warships with enough firepower to demolish a local starsystem, just to kill an ant.
Bottom line, construct the object instance, read the property.

Treating different objects the same? Iterator?

Sorry if something similar has been asked before. I'll try and be specific as possible.
I'm working on a quiz/study flash card application in c#. That would allow a user to create a number of study cards for self assessment. I would like the user to have the ability to create different types of card i.e. one where there is just a question and the answer, say both held as strings, one where there is a question and then multiple choices of answer and one where these is a phrase with words missing. Ideally I'd like to leave this open to extension later e.g. I might want to add a question that consists of a diagram or image where the missing words were labels that needed to be supplied.
Designing each of these things individually is probably do-able. Where I'm stuck is knowing how to design this in such a way that the user can attempt to take the test and the system can loop through the cards in such a way that the next card the user is presented with is any random one from the set and can be any one of the types I've mentioned below. I could define some sort of common interface say ICard and iterate through a collection of that type but am I always going to have to actually know what type I have so I can display what's needed for that particular card to the user e.g. display the multiple choices if it's a multiple choice type of card. Something about that kind of design doesn't seem quite right but I'm not sure of what other approach to take.
Thanks
Use ICard for the general card and some other interface for each type of card.
class MyCard: IMyCard, ICard
{ ... }
Loop through using ICard and when you get to the rendering part use
if(object is IMyCard)
renderIMyCard();
To determine which specific type of card you are working with. Strictly speaking, you don't really need to use an interface for each of the types but using an interface will make the code easier to Unit test if you do.
The other way you might go about this is to just embed the type of card in ICard as an enum property. But I think the interface method will serve you better in the long run.
Define model classes for each type of card, with a common base interface. Then, define corresponding View classes which handle rendering for those model classes. Here's an example:
Models:
interface IFlashCard { ... }
class MultipleOptionFlashCard : IFlashCard
{
String question;
List<String> answerOptions;
// etc.
}
Views
interface IFlashCardView
{
render();
}
class MultipleOptionFlashCardView : IFlashCardView
{
public void render()
{
// show textbox for question
// show radio buttons for answer options
}
}
Finally in the render phase,
IFlashCard flashCard = getNextFlashCard();
IFlashCardView flashCardView = mapModelToView(flashCard);
flashCardView.render();
where you map the model to the view in any number of ways, such as:
IFlashCardView mapModelToView(IFlashCard card)
{
if (card is MultipleOptionFlashCard)
{
return new MultipleOptionFlashCardView(card);
}
else ...
}
If you are using WPF, you can define a DataTemplate to directly map a model class to a set of controls, so this process becomes simpler and DRYer.

Building Generic Apps - Allowing Customer-specific Options

I've built an open source application, and I'd be curious to know how others are handling customer-specific requests. It's important to me to keep the app simple; I'm not trying to make it all things for all people. Apps can get bloated, complex, and just about unusable that way. However, there are some customer-specific options that would be nice (it just wouldn't apply to all customers). For example...
Say we have a domain entity called Server. In the UI, we let a customer pick from a list of servers. For one company, it's helpful to filter the servers by location (US, Germany, France, etc...). It would be easy enough to add a server property like this:
public class Server
{
public Location Location { get; set; }
// other properties here
}
My concern is that Server could become bloated with properties over time. And even if I only add location, not all customers would care about that property.
One option is to allow for user-defined fields:
public class Server
{
public string UserField1 { get; set; }
public string UserField2 { get; set; }
public string UserField3 { get; set; }
// etc...
// other properties here
}
Is that the best way to handle this? I don't like the fact that type safety is gone by making everything a string. Are there other/better ways that people are handling issues like this? Is there even a design pattern for something like this?
In my opinion, a good design pattern for something like this is to use schemas at the database level and then basic inheritance at the class level.
CREATE TABLE dbo.A (
ColumnA INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
ColumnB VARCHAR(50),
ColumnC INT,
etc.
)
And now we have a client who needs some specific functionality, so let's create an extension to this table in a different schema:
CREATE TABLE CustomerA.A (
ColumnA INT NOT NULL PRIMARY KEY,
Location VARCHAR(50)
)
But now we have another client who needs to extend it differently:
CREATE TABLE CustomerB.B (
ColumnA INT NOT NULL PRIMARY KEY,
DataCenterID INT
)
Though the fields may not be relevant, you get the idea, and so now we need to build the customer specific domain models here:
public abstract class A
{
public int ColumnA { get; set; }
public string ColumnB { get; set; }
public int ColumnC { get; set; }
}
public class CustomerA_A : A
{
public string Location { get; set; }
}
public class CustomerB_A : A
{
public int DataCenterID { get; set; }
}
And so now when we need to build something for Customer A, we'll build their subclass, and for Customer B theirs, and so on.
Now, FYI, this is the beginnings of a very dynamic system. I say that because the piece that's missing, that's not yet dynamic, is the user-interface. There is a significant number of ways that can be accomplished, but way outside the scope of this question. That is something you'll have to consider. I say that because the way you manage the interface will determine how you even know to build which subclass.
I hope this has helped.
The usual approach early on is to use the config XML files for this sort of thing. But programming for client-specific needs requires a whole mindset around how you program. Refer to this answer to a similar question.
Of course it always depends on how much customization you want to allow. In our product we went as far as enabling users to completely defined their own entities with properties and relations among them. Basically, every EntityObject, as we call our entities, in the end consists of a value collection and a reference to a meta-model describing the values within them. We designed our own query language that allows us to query the database and use expressions that are translate-able to any target language (although we currently only do SQL and .net).
The game does not end there and you quickly find that things like validation rules, permissions, default values and so on become a must have. Of course all of this then requires UI support, at least for the execution of the meta-model.
So it really depends on the amount of adjustment a end-user should be able to perform. I'd guess that in most cases simple user fields, as you described, will be sufficient. In that case I would provide a single field and store JSON text within that. In the UI you can then provide at least a semi-decent UI allowing structure and extensibility.
Option 1: Say "no". :-)
And while I say that (half) jokingly, there is some truth to it. Too often, developers open themselves up to endless customization by allowing one or two custom features, setting the snowball in motion.
Of course, this has to be balanced, and it sounds like you may be doing this to an extent. But if you truly want to keep your app simple, then keep it simple and avoid adding customizations like this.
Option 2: Inheritance.
If you really need to add the customization, I would lean the way of building a base class with all "standard" options, and then building customer-specific classes containing customer-specific optimizations.
For example:
public class Server
{
// all standard properties here
}
Then for Joe's Pizza, you can have:
public class JoesPizzaServer : Server
{
public Location Location { get; set; }
}
The side-benefit to this is that it will allow you to base your presentation views off of the client-specific (or base) models.
For example, in MVC you could set up your view models like this, and then you could have specific views for each customer.
For example, Bob's Burgers would have its own view on the base model:
#model MyApp.Server
#* implement the base form *#
And Joe's Pizza's view would use the custom model:
#model MyApp.JoesPizza
#* implement the base form -- a partial view -- with addtional custom fields
MVC does a really good job of supporting this type of pattern. If you're not using MVC (maybe WPF or Web Forms), there are still ways to leverage partial "view" files for accomplishing something similar.
Of course, your database can (and probably should) support a similar inheritance model. Entity Framework even supports various inheritance models like this.
I may be wrong here, but it looks like you want to handle different versions of your software with the same code base. I can think of two approaches for this:
Actually define different versions for it and handle changes for each client. This won't give you problems from the domain-modeling point of view, but will require a supporting infrastructure, which will have to scale according to your client requirements. There are some related questions out there (e.g. this, this and this).
Handle this at the domain-model level, as a user-defined configuration. The advantage of this approach is that you don't have to incorporate multiple versions of your software, but this comes at the expense of making your model more generic and potentially more complex. Also your tests will surely have to be adapted to handle different scenarios. If you are going in that direction I would model an object representing the attribute (with a name and a value) and consider the Server class as having a collection of attributes. In that way your model still captures your requirements in an OO style.
HTH
I approach from Python that I think would work rather well hear is a dictionary. The key is your field name, the value is the, errrrr... value ;)
It'd be simple enough to represent in a database too.

Avoiding magic strings and numbers

I am working on an application that has been edited by various programmers over the past few years and I have stumbled across a problem with using String Literals to access MenuItems.
For Example: in many places there is code like
mainMenu.MenuItems[1].MenuItems[0].Visible=true;
or
mainMenu.MenuItems["View"].MenuItems["FullScreen"].Visible=true;
how do I change the Strings used to identify the MenuItem and catch all of the places that it is being used for access? The menus and menuitems are declared as public and are used throughout this large application
What is the right way prevent the use of these magic indexes from being used. I forsee things being broken everytime a new item is added or the name is changed.
P.S. I have started using an enumerated dictionary approach in which every menuItem is paired with a key. but this still does not force other developers to use my implementation nor is it the most elegant solution to question 2
Give each menu item a name in the WinForms designer (I assume), and then refer to it by that name.
Then just use this in your code:
menuExit.Visible = false;
If the menu items are added programmatically, do this:
class MyForm : Form
{
private MenuItem menuExit;
...
myMenu.Items.Add(menuExit = new MenuItem(...));
...
}
and then still access it by the menuExit name. The key to avoiding magic numbers and strings is to just keep a direct reference to whatever it is you want to refer to. As a bonus, you can now rename this vairable safely using F2.
Romkyns answer is the correct one for this scenarion however if you do need to use string literals in your code I would alwasy keep them in public static classes such as:
public static class Constants
{
public static class Menu
{
public static readonly string FirstMenuName = "Menu 1";
...
}
public static class OtherCateogry
{
...
}
}
You can then access them by Constants.Menu.FirstMenuName.
As for definitively preventing other devs from using literals throughout code - you might have to make recourse to the Rod of Correction (sturdy metal ruler) ;).

Best way to get a list of differences between 2 of the same objects

I would like to generate a list of differences between 2 instances of the the same object. Object in question:
public class Step
{
[DataMember]
public StepInstanceInfo InstanceInfo { get; set; }
[DataMember]
public Collection<string> AdHocRules { get; set; }
[DataMember]
public Collection<StepDoc> StepDocs
{...}
[DataMember]
public Collection<StepUsers> StepUsers
{...}
}
What I would like to do is find an intelligent way to return an object that lists the differences between the two instances (for example, let me know that 2 specific StepDocs were added, 1 specific StepUser was removed, and one rule was changed from "Go" to "Stop"). I have been looking into using a MD5 hash, but I can't find any good examples of traversing an object like this and returning a manifest of the specific differences (not just indicating that they are different).
Additional Background: the reason that I need to do this is the API that I am supporting allows clients to SaveStep(Step step)...this works great for persisting the Step object to the db using entities and repositories. I need to raise specific events (like this user was added, etc) from this SaveStep method, though, in order to alert another system (workflow engine) that a specific element in the step has changed.
Thank you.
You'll need a separate object, like StepDiff with collections for removed and added items. The easiest way to do something like this is to copy the collections from each of the old and new objects, so that StepDiff has collectionOldStepDocs and collectionNewStepDocs.
Grab the shorter collection and iterate through it and see if each StepDoc exists in the other collection. If so, delete the StepDoc reference from both collections. Then when you're finished iterating, collectionOldStepDocs contains stepDocs that were deleted and collectionNewStepDocs contains the stepDocs that were added.
From there you should be able to build your manifest in whatever way necessary.
Implementing the IComparable interface in your object may provide you with the functionality you need. This will provide you a custom way to determine differences between objects without resorting to checksums which really won't help you track what the differences are in usable terms. Otherwise, there's no way to determine equality between two user objects in .NET that I know of. There are some decent examples of the usage of this interface in the help file for Visual Studio, or here. You might be able to glean some directives from the examples on clean ways to compare the properties and store the values in some usable manner for tracking purposes (perhaps a collection, or dictionary object?).
Hope this helps,
Greg

Categories