Probably I need a design pattern here: I have a factory that produces instances by the type. I want the user to be able to choose the type, so I need a caption for the type, then a list of the the common ancestor of the types.
Now, I'd like to enumerate the list, and print the captions. (No can do that, the static caption properties are inaccessible from the ancestor)
Then, I'd like to print the caption of an instance. Unable to do that, since the class properties are inaccessible from an instance.
If I use a dictionary, that connects the type and the caption, captions are again, inaccessible from the instance, nor the type, etc.
I've been using Delphi for 20 years, and used virtual constructors and virtual class properties every day. I kind of like C#, but after years, I still don't have comfy solution for such things. (Thanks for the help in advance)
Using System.Reflection you can enumerate all types of an assembly, check if they derive from a given base type or implement a certain interface.
You can also access non public fields or properties (static or instance).
So may be this is the way to go.
If the class hierarchy is you own code, you also could/should simply redesign it a little to get access to the members that are now restricted..
Related
I'm developing a complex desktop client with C#, which is mainly for some scientific analysis work. The class hierarchy of my project is very complicated. The problem is that, a large amount of parameters should be able to be modified by the user at the entrance of the client.
However, many parameters are very deep in the class hierarchy (I mean the composition hierarchy, not inheritance). As a result, classes closed to the top levels must take a lot of arguments in the constructor, because they are passed all the way up from different classes at the bottom levels.
What's the best practices to handle problems like this? I have 3 ideas:
Global static variables: Just create a Constants class and store these params as static fields, like Constants.FOO, Constants.BAR.
Singleton class: Create a singleton class, and initialize it at the entrance of program. Get these params like Constants.GetInstance().FOO.
For every class, receive lower-level params in the constructor, which makes the constructor signature verbose and complicated. For example, a mid-level frequently-used class may take 15 arguments in the constructor.
If I use global variables or a singleton too often, the code will become very coupled. But if I do not use them, lots of params must be passed and received along the class hierarchy again and again. So how would a complicated commercial software do to solve this problem?
For example, the program creates a LevelOne object at the topmost level. The LevelOne contains fields like LevelTwoA and LevelTwoB. And a LevelTwoA object contains fields like LevelThree and so on. Then if the user wants to specify the value of a LevelTen field when creating the LevelOne, the value of LevelTen must be passed from the constructor of LevelOne to LevelNine.
And take a Car as an example, what if the user want to specify the Radius of a certian Gear when creating a Car? The Gear object must be at the bottom level of the whole hierarchy. However, a Car should not take a double radiusOfACertianGear as an argument in its constructor, because it's too trivial.
Thanks for all comments and answers for my question. Dependency injection is exactly the solution. I have spend one afternoon learning how dependency injection works. A class should not produce other classes(dependencies) in there constructor, it should receive one from the argument instead.
And you also need one or more configuration files/classes to provide the values of all the parameters. Then create an injector/factory to create all needed objects/dependencies based on the configurations.
I would create a builder to construct the composing parts and fit them nicely together.
I have an object named currHotel. It holds values like:
address
bigImageUrl
Category
Chain
City
and so on
This object contains another object inside it, with different values, named - Ben.Hotel.HotelFinder.BC_Hotel:
How can I access the object Ben.Hotel.HotelFinder.BC_Hotel that's inside currHotel?
It doesn't appear in it, and I need some values from it:
As I understand it, the values that you want to access are on your base class? In that case, check the access modifiers on those fields/properties/methods, and make sure that they are exposed in the way you want.
The simplest (and least safe!) approach is to make everything public but depending on where you are trying to read those fields/properties/methods you may be able to get away with protected (accessible in derived classes) or internal (accessible anywhere in the same assembly) instead.
Edit:
Also remember that there is not really a BC_Hotel object "inside" current, but rather current is a BC_Hotel (since its class is derived from it), so all the fields on that base class are available directly on current, depending on access (as I said above).
your currHotel is an instance of type Ben.Hotel.HotelFinder.BC_Hotel.
From the screenshot, the currHotel doesn't have another property of type Ben.Hotel.HotelFinder.BC_Hotel.
My company has a base database model class that is subclassed by particular instances of our product. The class represents primary keys in a database. The base class has a field, which we'll call AlwaysPresent, which is common to all instances of the product and is not used in querying.
abstract class BaseClass
{
private string AlwaysPresent
}
But it is a requirement that subclasses add at least one more field, as we will use reflection later to treat those other fields as database column names for a query. If there are no other fields, we can't query.
So, my question: is it possible to use C#'s reflection capabilities to force a non-abstract subclass to define new fields without specifying their names?
I am a Python programmer by trade, and I know exactly how to solve this kind of problem in Python using metaclasses. To my knowledge, C# does not have metaclasses. And I cannot raise an exception in the base class constructor, because (for various reasons) we don't use constructors for these classes (just initializers), and even if we did the base class constructor could be overridden.
Reflection cannot be used to force something. At least not at compile time. Via reflection you can read how a type is. In your case you can probably check its fields and throw an exception if required at run time.
In any case usually it is much better to use properties instead of fields. Properties are more extensible and better to hide the internal structure of a class.
A common way to enforce a specific design (properties or methods definition) of a class is to use interfaces.You can have also a class that implement more than one interface.
If properties names or fields are not know when designing the interface you cannot enforce your requirements at compile time but only at run time.
Another common c# technique is to decorate properties or fields with attributes. Maybe you can create a custom attribute and at run time check for fields with that attribute (always with reflection).
This can be done with aspects, specifically PostSharp. It allows you to execute custom code during compilation (in fact, it hooks on postcompile action) in the CompileTimeValidate:
http://www.postsharp.net/blog/post/Architectural-Validation
You can of course replace PostSharp with any custom code triggered on postcompile at build-time.
Turns out this is not a feature in C#, but you can write it like this to force people to implement it
abstract class BaseClass
{
private abstract string GetAlwaysPresent();
}
In OOP languages like C# or VB.NET, if I make the properties or methods in a super class protected I can't access them in my Form - they can only be accessed in my class that inherits from that super class.
To access those properties or methods I need to make them public, which defeats encapsulation, or re-write them into my class, which defeats inheritance.
What is the right way to do this?
If you have code which needs to ask an Class to perform a specific operation but the class does not present your code with a means to do that then the Class doesn't fulfill you codes requirements.
Its bit like saying I've got a Car (Automobile) that has a protected steering wheel so I can't access it. The car is no use to me.
Either make those members Public (or at least internal) and use them or ditch the class and use one that gives your consuming code the features it needs.
Perhaps what you are really looking for is an interface. The interface contains the members your code needs and you implement that interface on your class. The advantage here is that your class can determine that the members are being accessed via this Interface rather than an inheriting subclass.
"need to make them public which defeats encapsulation"
Don't conflate good design with the icky visibility rules. The visibility rules are confusing. There are really two orthogonal kinds of visibility -- subclass and client. It's not perfectly clear why we'd ever conceal anything from our subclasses. But we can, with private.
Here's what's important. Encapsulation does not mean hiding. Protected and private are not an essential part of good encapsulation. You can do good design with everything being public (that's the way Python works, for example).
The protected/private stuff is -- mostly -- about intellectual property management: are you willing to commit (in a legally binding, "see-you-in-court-if-it-doesn't-work" way) to an interface? If your software development involves lawyers, then you care about adding protect and private to the things you're not committed to.
If you don't have to cope with lawyers, consider doing encapsulation right but leave everything public.
Sorry, it's not clear what you mean by "in my Form" - what is the relationship between your Form and your two classes? If your classes are controls in the same project, and you want to access properties from the form, you should use the 'internal' keyword.
There are at least three ways you can limit who can use some particular instance method of particular class instances:
Define the method as `protected`, `internal`, or `private`. In the first case, an instance method will only be usable from within derived-class methods of the same instance; in the second case, all classes within the assembly will have access to those methods, but classes outside won't; in the third case, no outside classes, even derived ones in the same assembly, will have access, unless their code is nested within the declaring class.
Define the method as `public`, but have the classes that create instances keep them private and never expose them to the outside world. Anyone wanting to invoke an instance method on an object has to have an instance to invoke it on. If a class holds instances but never exposes direct references to them, the only instance methods that can ever be used on those instances will be those which the holding classes uses itself.
Define the method as `public`, but have a constructor which accepts a location into which one or more delegates to private methods may be stored. Code with access to those delegates will be able to call the methods referred to thereby, but other code will not (except by using Reflection in ways which I think are only usable in full-trust scenarios).
If Reflection in non-full-trust scenarios would allow unbound delegates to be bound to arbitrary object instances, one could use nested classes to reinforce #3 so that one would have to access private fields to gain illegitimate access to the private functions; that would definitely be forbidden outside full-trust scenarios.
Here is the situation for which I am trying to find a suitable design.
I need to store profiles of numbers. A profile is just a series of numbers. They can be of either int, float or decimal type. Each profile has a ProfileDescription field based on an ennumeration.
Each Profile has a collection of ProfileVersion Objects. Each ProfileVersion object has a collection of ProfileValue objects. These ProfileValue objects are where the actual numerical values of the required type are stored.
My initial design idea was to make Profile, ProfileVersion and ProfileValue generic. I hit a problem when I want to have a List of Profiles of different types, which I cannot have. I could use an ArrayList instead, but then i would have to cast out the data within it.
I though it might be possible to make just ProfileVersion and ProfileValue generic, and then have the Profile Object assign a type to the ProfileVersion depending on the value of the ProfileDescription field, but I cannot find a way to do this.
Another thought was I should use a ProfileBase class and then subclass it with either a GenericProfileClass or IntProfile, FloatProfile and DecimalProfile, but this wouldn't really give me any advantage over having each class being generic, as I would have to cast out the subclass each time anyway.
I would appreciate your thoughts on the best design approach for this situation.
Thanks
Grzenio's idea is correct. Each of your profile classes could be made to be implementations of an IProfile object, and then your container could be:
class ProfileList : IList<T> where T: IProfile
Thus the only constraint you'll have is the interface, not the specific type or a casted base class.
As for:
Another thought was I should use a
ProfileBase class and then subclass it
with either a GenericProfileClass or
IntProfile, FloatProfile and
DecimalProfile, but this wouldn't
really give me any advantage over
having each class being generic, as I
would have to cast out the subclass
each time anyway.
The benefits would really depend on the level of abstractions that you make for your classes. If designed properly you can ideally have operation/business logic/or manager classes that can accept any of those base types (again via generics) without having to know the specific cast.
I am not sure if I understand your problem correctly (pasting the code that doesn't work would help), but I think that you could try to create interfaces IProfile, IProfileVersion, etc. and make the generic class inherit the interface Profile<T>:IProfile.
What you are trying to do in not easy anyway, because there is no base numeric type in C# sadly.