Trying to achieve additional scoping in C# Properties - c#

I'm working on a utility that generates lots of C# classes. Most generated classes are small, but some get up to 50+ public members. I would like to be able to add an additional level of scoping just to reduce clutter and make them more IntelliSense-friendly.
For example, say I generate a class Foo with the following members:
Apple, Banana, Cantaloupe, Dog, Elephant, Fox, Geranium, Hibiscus, Iris.
Instead of IntelliSense showing all 9 members when I type new Foo()., I want to be able to scope the properties to categories. For example, new Foo().Animals. would list Dog, Elephant, and Fox.
The only way I can think of to do this is to create an inner class for each category and creating a property on the parent class that returns an instance of the child class. This doesn't seem very elegant and I'm not sure if it's a good use of nested classes.
public class Scope
{
public FruitProperties Fruit { get; private set; }
public AnimalProperties Animals { get; private set; }
public FlowerProperties Flowers { get; private set; }
public Scope()
{
Fruit = new FruitProperties();
Animals = new AnimalProperties();
Flowers = new FlowerProperties();
}
public class FruitProperties
{
public string Apple { get { return "Apple"; } }
public string Banana { get { return "Banana"; } }
public string Cantaloupe { get { return "Cantaloupe"; } }
}
public class AnimalProperties
{
public string Dog { get { return "Dog"; } }
public string Elephant { get { return "Elephant"; } }
public string Fox { get { return "Fox"; } }
}
public class FlowerProperties
{
public string Geranium { get { return "Geranium"; } }
public string Hibiscus { get { return "Hibiscus"; } }
public string Iris { get { return "Iris"; } }
}
}

Related

Method Eat used in the class Lion. How can I set the value of eaten thing (living thing) as dead?

Eat Method in the Interface IAnimal in the AnimalWorld has a fuction in the class Lion. When an animal (Lion) eats a Living thing, the leaving thing dies.
ILIVING
namespace AnimalWorld
{
public interface ILiving
{
Status LifeStatus
{
get; set;
}
Status GetLifeStatus();
}
}
IANIMALS
namespace AnimalWorld
{
public interface IAnimals : ILiving
{
// List<IAnimals> Breed(string babyName);
string Name { get; set; }
IAnimals Breed(string babyName);
int Legs { get; }
void Eat(ILiving food);
}
}
LION
namespace AnimalWorld
{
public class Lion : IAnimals
{
public Lion(string name)
{
this.Name = name;
}
public Lion()
{
}
public Status LifeStatus { get; set; }
public Status GetLifeStatus()
{
return Status.Alive;
}
public string Name { get; set; }
public IAnimals Breed(string babyName)
{
var baby = new Lion(babyName);
return baby;
}
public int Legs
{
get { return 4; }
}
public void Eat(ILiving food)
{
return food;
}
}
}
PROGRAM
namespace AnimalWorld
{
internal class Program
{
public static void Main(string[] args)
{
var l = new Lion("first lion");
var firstBabyL = l.Breed("first baby lion");
var secondBabyL = l.Breed("second baby lion");
}
}
}
Since LifeStatus is a public property, it can be set from the Lion's Eat() method.
public void Eat(ILiving food)
{
food.LifeStatus = LifeStatus.Dead;
}
You need a method Die:
public interface ILiving
{
Status LifeStatus
{
get; set;
}
Status GetLifeStatus();
void Die();
}
Used as:
public class Lion : IAnimals
{
//...
void Die()
{
LifeStatus = Status.Dead;
}
//....
}
If I am getting this right, what you probably need as an answer is to keep setters private and provide methods that express the behavior of your classes/interfaces instead.
Imagine LifeStatus being arbitrarily set at various positions all over your code, and suddenly, dying acquires a different meaning for your IAnimals. You will have to chase down all places where it has been set. Instead, if you have a method, you can do whatever you wish in the method, and all places where it has been invoked will not have to be changed in any way. You will "enforce" the new meaning directly inside the class.
Now, why dying might change meaning, is a different story...

Implement multiple times the same generic interface that includes properties with different type parameters

Well from the beginning, I've got a simple generic interface:
public interface IItemContainer<T> where T : Item
{
T ChosenItem { get; set; }
}
And an class that implements it multiple times:
public class ChosenItemsContainer : IItemContainer<FabulousItem>, IItemContainer<NiceItem>, IItemContainer<GreedyItem>
{
public FabulousItem ChosenItem { get; set; }
NiceItem IItemContainer<NiceItem>.ChosenItem { get; set; }
GreedyItem IItemContainer<GreedyItem>.ChosenItem { get; set; }
}
I can't make the ChosenItems of types NiceItem and GreedyItem public, and also I can't access it like this:
ChosenItem<GreedyItem> = new GreedyItem();
cuz' I've got an error:
'GreedyItem' is a type, which is not valid in the current context
Is there anyway to use those props in this manner or I've got it all wrong and should do It with Dictionary or other way?
When you like to keep your generic IItemContainer you can implement a GetChosenItem and SetChosenItem method like this.
public class ChosenItemsContainer : IItemContainer<FabulousItem>, IItemContainer<NiceItem>, IItemContainer<GreedyItem>
{
FabulousItem IItemContainer<FabulousItem>.ChosenItem { get; set; }
NiceItem IItemContainer<NiceItem>.ChosenItem { get; set; }
GreedyItem IItemContainer<GreedyItem>.ChosenItem { get; set; }
public T GetChosenItem<T>()
where T : Item
{
return ((IItemContainer<T>)this).ChosenItem;
}
public void SetChosenItem<T>(T value)
where T : Item
{
((IItemContainer<T>)this).ChosenItem = value;
}
}
Which comes very close to what you were trying to do.
container.SetChosenItem<NiceItem>(new NiceItem());
Yours is a case explicit interface implementations were made for. You give your conflicting items a unique name and forward the items to the interface. That also avoids any naming confusions:
public class ChosenItemsContainer : IItemContainer<FabulousItem>, IItemContainer<NiceItem>, IItemContainer<GreedyItem> {
public FabulousItem ChosenFabulousItem { get; set; }
public NiceItem ChosenNiceItem { get; set; }
public GreedyItem ChosenGreedyItem { get; set; }
FabulousItem IItemContainer<FabulousItem>.ChosenItem {
get {
return ChosenFabulousItem;
}
set {
ChosenFabulousItem = value;
}
}
NiceItem IItemContainer<NiceItem>.ChosenItem {
get {
return ChosenNiceItem;
}
set {
ChosenNiceItem = value;
}
}
GreedyItem IItemContainer<GreedyItem>.ChosenItem {
get {
return ChosenGreedyItem;
}
set {
ChosenGreedyItem = value;
}
}
}
Assignment is simple:
container.ChosenFabulousItem = new FabulousItem();
container.ChosenNiceItem = new NiceItem();
container.ChosenGreedyItem = new GreedyItem();
If you have more complex conversion logic in the background (e.g. you assign a FaboulousItem and need to convert it into a NiceItem), you can do so by providing getters and/or setters for your public properties.
It's completely wrong. As you should know you cannot make same names for member items (properties, fields etc. ). It will confuse compiler.
I would suggest to modify your interface a bit like :
public interface IItemContainer
{
List<Item> ChosenItems { get; set; }
T ChosenItem<T>() where T : Item;
}
Now in your implementation :
public class ItemContainer : IItemContainer
{
IItemContainer.ChosenItems
{
get { // your implementation
}
set { // your implementation
}
}
T IItemContainer.ChosenItem<T>()
{
return ((IItemContainer)this).ChosenItems.OfType<T>().FirstOrDefault();
}
}
This method will let you store different objects that derive from Item and return desired one using ChosenItem<T>() method.
EDIT:
I've got another interface which operates on List of Items, cuz' some submodules works only on one Item, and some only on set. I need also to store an instance of each implemented type independently.
You can always use something like a factory collection ( dont know if the name is correct ).
public class ChosenItemCollection
{
Dictionary<Type, Item> _fac = new Dictionary<Type, Item>();
public T Add<T>(T item) where T : Item
{
if(!_fac.ContainsKey(typeof(T))
{
_fac.Add(typeof(T), item);
}
else
{
_fac[typeof(T)] = item;
}
}
public T GetChosenItem<T>() where T : Item
{
if(_fac.ContainsKey(typeof(T))
return _fac[typeof(T)];
return null;
}
}
Then in your interface instead of List<Item> ChosenItems you can do ChosenItemCollection ChosenItems.
Using this in your example :
GreedyItem item = // ...
ItemContainer.ChosenItems.Add(item);
ItemContainer.ChosenItem.ChosenItem<GreedyItem>();
I think Pidon has a nice solution. But could result in a runtime error when using not implemented Item derives.
Another solution could be adding properties which will do the casts to the implemented types:
public class ChosenItemsContainer : IItemContainer<FabulousItem>, IItemContainer<NiceItem>, IItemContainer<GreedyItem>
{
// these properties are only visible when casting to the correct
// interface. Which the public properties below will do.
FabulousItem IItemContainer<FabulousItem>.ChosenItem { get; set; }
GreedyItem IItemContainer<GreedyItem>.ChosenItem { get; set; }
NiceItem IItemContainer<NiceItem>.ChosenItem { get; set; }
// return this as IItemContainer<FabulousItem>
public IItemContainer<FabulousItem> AsFabulous
{
get
{
return (IItemContainer<FabulousItem>)this;
}
}
// return this as IItemContainer<NiceItem>
public IItemContainer<NiceItem> AsNice
{
get
{
return (IItemContainer<NiceItem>)this;
}
}
// return this as IItemContainer<GreedyItem>
public IItemContainer<GreedyItem> AsGreedy
{
get
{
return (IItemContainer<GreedyItem>)this;
}
}
}
ChosenItemsContainer container = new ChosenItemsContainer();
container.AsFabulous.ChosenItem = new FabulousItem();
container.AsNice.ChosenItem = new NiceItem();
container.AsGreedy.ChosenItem = new GreedyItem();
This way each implemented type has it's own ChosenItem instance. I think this is a clean solution without cluttering of generic <T> in code.

How to make a static array containing information from all derived classes

I have a interface called Species, and derived classes containing each species with literal information about the species. See below:
public interface Species
{
string database { get; }
string genus { get; }
string binomialName { get; }
}
public class Monosiga_brevicollis : Species
{
public string database { get {return "monosiga";} }
public string genus { get {return "Choanoflagellatea";} }
public string binomialName { get {return "Monosiga_brevicollis";} }
}
public class Amphimedon_queenslandica : Species
{
public string database { get {return "queenslandica";} }
public string genus { get {return "Porifera";} }
public string binomialName { get {return "Amphimedon queenslandica";} }
}
This allows me to assign a species to an object, and then get information about where the database for that species is, or what genus the species is in.
How can I perform operation on all the derived classes of Speices. For example:
1) create a function:
public bool isSpecies(string binomial)
that allows me to check whether or not the inputted string is one of the pre-coded species by checking through the binomial names.
and 2) create a list
string[] allSpecies;
that contains all the binomial names in an array so I can use the array as default options for text boxes ect.
It seems like these should be instances of an implementation of the ISpecies interface, rather than separate classes. Something like the following:
public class Species : ISpecies
{
public string database { get; set; }
public string genus { get; set; }
public string binomialName { get; set; }
}
var speciesList = new List<ISpecies>()
var monosiga = new Species() {
database = "monosiga",
genus = "Choanoflagellatea",
binomialName = "Monosiga_brevicollis"
}
speciesList.Add(monosiga);
Once you've filled up your list, you can enumerate the binomial names like so:
var names = speciesList.Select(s => s.binomialName);
You can also check whether a species is present in the list by doing:
bool IsSpecies(string binomialName) {
_speciesList.Any(s => s.binomialName == binomialName);
}

Self-Referential Property array

I want to be able to loop through a Class Property that references its own properties. Why you may ask? Because it's easier to manage later on if I want to add more properties to that Class.
Let me explain more:
public interface IElementBox
{
string Filename { get; }
string FileDefinition { get; set; }
void ExtractFromFile(string stringData);
}
public abstract class Element
{
public Element(string stringData)
{
this.DefFromFile(stringData);
}
public string Name { get; set; }
protected abstract void DefFromFile(string stringData);
}
public class Solid : Element
{
public Solid(string stringData) : base(stringData) { }
public string SolidSpecificProperty { get; set; }
protected override void DefFromFile(string stringData)
{
// Assign SolidSpecificProperty from string
}
}
public class Liquid : Element
{
public Liquid(string stringData) : base(stringData) { }
public string LiquidSpecificProperty { get; set; }
protected override void DefFromFile(string stringData)
{
// Assign LiquidSpecificProperty from string
}
}
public class Gas : Element
{
public Gas(string stringData) : base(stringData) { }
public string GasSpecificProperty { get; set; }
protected override void DefFromFile(string stringData)
{
// Assign GasSpecificProperty from string
}
}
public abstract class ElementBox<T> : IElementBox where T : Element
{
public List<T> Elements { get; set; }
public List<T> GetElementsFromName(string name)
{
return this.Elements.FindAll(x => x.Name == name);
}
public abstract string Filename { get; }
public string FileDefinition { get; set; }
public abstract void ExtractFromFile(string filename);
}
public class SolidBox : ElementBox<Solid>
{
public override string Filename
{
get { return "Solid.txt"; }
}
public override void ExtractFromFile(string stringData)
{
this.Elements.Add(new Solid(stringData));
}
}
public class LiquidBox : ElementBox<Liquid>
{
public override string Filename
{
get { return "Liquid.txt"; }
}
public override void ExtractFromFile(string stringData)
{
this.Elements.Add(new Liquid(stringData));
}
}
public class GasBox : ElementBox<Gas>
{
public override string Filename
{
get { return "Gas.txt"; }
}
public override void ExtractFromFile(string stringData)
{
this.Elements.Add(new Gas(stringData));
}
}
public static class DataDefinition
{
public static SolidBox SolidBox { get; set; }
public static LiquidBox LiquidBox { get; set; }
public static GasBox GasBox { get; set; }
public static IElementBox[] ElementBoxes = new IElementBox[] { DataDefinition.SolidBox, DataDefinition.LiquidBox, DataDefinition.GasBox };
}
public static class Loader
{
public static void LoadInfo()
{
for (int elementBoxNb = 0; elementBoxNb < DataDefinition.ElementBoxes.Length; elementBoxNb++)
{
string dataFilepath = DataDefinition.ElementBoxes[elementBoxNb].Filename;
System.IO.StreamReader sr = System.IO.File.OpenText(dataFilepath);
DataDefinition.ElementBoxes[elementBoxNb].ExtractFromFile(sr.ReadToEnd());
}
}
}
The whole purpose of this structure is to be able to define all the object properties in a text file. So that all the SolidBox.Elements objects are dynamically assigned from that text file definition.
My questions are as follow:
Will the property array in DataDefinition be referenced by value. Which would mean that all my data assignation would get absorbed in the void?
If yes (or no..), is their a better way of doing the whole thing / What would be the best way to do it?
I've been working on that data structure for a while now I'm getting proud of what I could achieve. I would be sad if all that was done for nothing. Although, if one if you can provide me with a better/optimal way of doing the whole thing, I will be grateful and throw my code in my archive folder.
Also, keep in mind that this is an example of the data structure. It does not reflect exactly what my code looks like and is made so to ease comprehension and reading.
Don't hesitate to ask questions if more information is needed.
Deserialization (reading objects in from a persistent medium) has been solved a zillion different ways. Try using Data Contracts, like this answer demonstrates. You just need to add a few attributes to your properties to indicate what you want serialized and then it does just about all of the work for you.
This won't do what you want. The array will contain references to the objects referenced by the properties at the time it is initialised, which in this case will be null. If you assign something to the SolidBox property the associated element of the array won't change, and vice-versa.

In C#, can I hide/modify accessors in subclasses?

I'm not even sure what this principle is called or how to search for it, so I sincerely apologize if it has been brought up before, but the best way to do it is with an example.
class Properties
{
public string Name { get; set; }
}
class MyClass
{
class SubProperties: Properties
{
public override Name
{
get { return GetActualName(); }
set { SetActualName(value); }
}
}
public SubProperties ClassProperties;
private string GetActualName()
{
return SomeFunction();
}
private void SetActualName(string s)
{
ClassProperties.Name = SomeOtherFunction(s);
}
}
The idea is to have any object that instantiates MyClass have a fully accessible property ClassProperties. To that object, it would look exactly like a Properties object, but behind the scenes, MyClass is actually computing and modifying the results of the fields. This method of declaration is obviously wrong since I can't access GetActualName() and SetActualName() from within the SubProperties definition. How would I achieve something like this?
Are you looking for something like this?
abstract class Properties
{
public abstract string Name { get; set; }
}
class MyClass
{
private class SubProperties : Properties
{
private MyClass myClass;
public SubProperties(MyClass myClass)
{
this.myClass = myClass;
}
public override Name
{
get { return this.myClass.GetActualName(); }
set { this.myClass.SetActualName(value); }
}
}
private string name;
public MyClass
{
this.MyClassProperties = new SubProperties(this);
}
public Properties MyClassProperties { get; private set; }
private string GetActualName()
{
return this.name;
}
private void SetActualName(string s)
{
this.name = s;
}
}
You need to pass a reference to a MyClass instance to the SubProperties instance if you want to access MyClass methods from SubProperties.
public virtual string Name { get; set; }

Categories

Resources