This may just be me showing my lack of knowledge / bad programming practice, but i'm curious to know if:
a) This already exists
b) If it doesn't exist, if it's bad programming practice to do so
But here's my question:
Suppose I have a class, let's call it "Computer" and it holds data of all the computers in a company. Now, it just so happens that this company has thousands of Dell computers and thousands of HPs and nothing else. (Again please stick with me here, this is just an example to illustrate my point)
Now, I could define my class as follows:
Public Class Computer
Dim Type as string
Dim SerialNumber as string
Dim User as String
...
End Class
Now, in my code I create two lists:
Dim DellComps as new list(of computer)
Dim HPComps as new list(of computer)
Obviously, for the DellComps, all them will have .Type = "Dell" and for the HPComps, all will have .Type = "HP"
Now, I know I could set this variable in the constructor very easily, but I'm wondering if there is a smarter way to declare the variable inside the class - Similar to the VB Shared / C# Static statement where all the instances of the class share the same variable.
My thoughts are:
Inherit the class and create a shared variable in the child class
Just leave it as is and declare the Type var in the constructor
Maybe this is something that could be done via interfaces somehow
MOST PROBABLE - something i just don't know about
Thanks and I hope what I'm asking makes sense!!!
The closest thing you'd have is done with the abstract keyword. You would have an abstract class Computer, that would then be overridden by the concrete subclasses DellComputer and HpComputer. A crude (C#) example would be:
public abstract class Computer
{
public string Type { get; protected set; }
}
public class DellComputer : Computer
{
public DellComputer()
{
this.Type = "Dell"
}
}
You generally don't want to share a single variable among a ton of instances because that breaks encapsulation, and more realistically can become a big problem when attempting to unit test code. So the pure form of what you're talking about isn't a terribly good idea, but the realistic use case is pretty common, and definitely supported.
EDIT: As part of the comments below, here's a different approach that uses the very closely related virtual keyword!
public abstract class Computer
{
public virtual string Type { get; }
}
public class DellComputer : Computer
{
public override string Type
{
get {
return "Dell";
}
}
}
If you are always setting a flag in the constructor indicating the type of computer (which is NOT a typical business object scenario, where the type can be edited), chances are that you can really solve your problem using subclasses.
Subclass Computer to create DellComputer and HpComputer classes.
When creating lists of each type of computer, one approach is to have a master list of all computers and use Linq's Enumerable.OfType(TResult) to select instances that match the type you are interested in.
If indeed you want the type of class to be editable after the class is created, instead provide a property to modify the type of computer. You may for convenience provide a constructor overload that also sets the property (though I would shy away from that personally). If you do, have that constructor overload use the property to set the type.
UPDATE
Example of what the factory pattern might look like.
public abstract class Computer
{
public virtual string Type { get; }
}
public class DellComputer : Computer
{
public override string Type
{
get { return "Dell"; }
}
}
public class HpComputer : Computer
{
public override string Type
{
get { return "HP"; }
}
}
// Here I'm using an enum to indicate the type desired. You might use a string
// or anything else that makes sense in your problem domain.
public enum ComputerType
{
Dell = 1,
Hp = 2
}
public class ComputerFactory
{
public Computer Create(ComputerType type)
{
switch (type)
{
case ComputerType.Dell:
return new DellComputer();
case ComputerType.Hp:
return new HpComputer();
default:
throw new InvalidArgumentException();
}
}
}
// Usage would be something like:
List<Computer> computers = new List<Computer>();
computers.Add(ComputerFactory.Create(ComputerTypes.Dell);
computers.Add(ComputerFactory.Create(ComputerTypes.Dell);
computers.Add(ComputerFactory.Create(ComputerTypes.Hp);
You could create a class that has a collection and other data
In this case PC would not have a type.
public class Computers
{
private List<Computer> pcs= new List<computer>();
public List<Computer> PCs get { return { pcs; } };
public String Brand { get; private set; }
public Computers(string brand) {Brand = brand;}
}
Regarding a static variable. You don't want all members of the class share Brand.
With the said just repeat the data in the constructor.
If a Dell has the same Properties as an HP then I would use the same class.
If you stated buying a new brand do you really want to create a new class or subclass?
If you want a structured list of brands then I would use and Enum rather than a separate class for each brand.
Related
I have an abstract class called Flight and its implement a interface called IFlight and it has a virtual method, another three classes that inherit from it, the only diffrence between those three classes is the implemantation of this method. Another thing that I want to do is implement a method that accepts as an argument an object of type IFlight (could be one of those three classes) and from them i want to access the members of the abstract class (Flight). Which way there is to implement such thing ?
Flight:
class AbsFlight: IFlight
{
public int ID { get; set; }
public string Start_Point { get; set; }
public virtual float Calculate_Price(float Base_Price)
{
return Base_Price;
}
}
One of the classes (The other two looks similar except the method "Calculate_Price"):
class Charter: AbsFlight
{
public override float Calculate_Price(float Base_Price)
{
return base.Calculate_Price(Base_Price) * 3;
}
}
Main:
private static void Some_Method(IFlight flight)
{
Console.WriteLine(flight.Calculate_Price(2)); //OK
Console.WriteLine(flight.ID); //Error
}
static void Main(string[] args)
{
List<IFlight> flights = new List<IFlight>();
flights.Add(new Regular());
flights.Add(new Charter());
flights.Add(new LowCost());
Main_SomeMethod(flights[0]);
}
Your current solution, in combination with some of the suggestions, will be a case of a mounted riding rider. You don't need an interface and a base class and testing for type.
You can solve your problem the way you're trying, with a base class and an interface. But it's overkill, and you have to kind of duplicate some stuff in the interface and the base class.
You can solve your problem with a simple base class and three derived classes where only Calculate_Price gets overridden. Put the common items in the base class. This is a very simple solution, easy to figure out, especially if C# and OOP is new to you.
You can also solve your problem with an interface and three classes, not derived. This has the disadvantage that you have to implement the interface in three classes. As Peter Csala points out, C# 8 has some language features that can help minimize this work, possibly making this just as simple as using only a base class and no interface. I am not too familiar with those features, so I can't judge whether it makes sense.
Then there is another option entirely. This touches on what zaitsman hinted at - that this is possibly an XY problem. Why do you want to distinguish between Regular, Charter and LowCost using classes derived from Flight/AbsFlight? Is it possible to just have an attribute that tells what price profile is used? Are there other fields and properties of a Flight that has nothing to do with the price, and yet also distinguishes flights? Perhaps just use one class.
About testing for class type. This is what we call code smell. Generally, if you test for class types a lot, then you defy the purpose of using classes and/or interfaces in the first place.
Your method should accept the type that has the properties it needs, in this case the AbsFlight class.
private static void Some_Method(AbsFlight flight)
{
Console.WriteLine(flight.Calculate_Price(2));
Console.WriteLine(flight.ID); //OK
}
But let's says the method must accept any IFlight. In this case, it can't be sure it received an AbsFlight; it has to check. After the check you can just cast.
private static void Some_Method(IFlight flight)
{
Console.WriteLine(flight.Calculate_Price(2));
if (flight is AbsFlight)
{
Console.WriteLine(((AbsFlight)flight).ID); //OK
}
}
With c#7 there is an additional construct you can use, if you think it is clearer:
private static void Some_Method(IFlight flight)
{
Console.WriteLine(flight.Calculate_Price(2));
switch (flight)
{
case AbsFlight absFlight:
Console.WriteLine(absFlight.ID); //OK
break;
}
}
It seems to be that you are doing something wrong that this is your requirement.
When you use an interface and pass it as an argument you want it to be common to all the objects that implement it.
Anyway, if you do want to do it. You might do something like:
if (flight is Flight)
{
Flight yourFlight = (Flight)flight;
// Here you can use anything you need from Flight, e.g: yourFlight.ID
}
class Program{
void Apple(){
List<Banana> apple = new List<Banana> { (new Banana(Cucumber, 5)), (new Banana(Dates, 6)) };
}
}
class Banana{
public Banana(Type eggplant, int feijoa){
new eggplant(feijoa);
}
}
class Cucumber{
public Cucumber(int feijoa){
}
}
class Dates{
public Dates(int feijoa){
}
}
basically it feeds a bunch of information from the program class to the Banana class, which then filters that information and uses it to create instances of a bunch of different classes.
the problem is within the Program class, where even though it registers that a Type is needed to complete the Banana constructor, when given a Type, like Cucumber or Dates, it says giving a type there is not considered valid in the given context, so i would like some help with understanding how to fix it, thanks in advance.
while structuring my program this way might seem weird and inefficient, it's mostly to help simplify viewing and editing the front end of my program.
you should use typeof operator while passing argument to constructor.
Like :
List<Banana> apple = new List<Banana> { (new Banana(typeof(Cucumber), 5)), (new Banana(typeof(Dates), 6)) };
However inside constructor you need to use Activator.CreateInstance(typeof(T), object[] args) to instantiate either Cucumber or Banana objects.
Also you better consider redesigning your class like :
class Banana<T> where T: new(){
public Banana(int feijoa){
Activator.CreateInstance(typeof(T), new object[]{feijoa}
}
so your snippet would be changed to :
List<Banana> apple = new List<Banana> { (new Banana<Cucumber>(5)), (new Banana<Dates>(6)) };
To get the Type instance of Cucumber class you should use typeof(Cucumber). So your constructors should change to look like the following:
new Banana(typeof(Cucumber), 5)
new Banana(typeof(Dates), 6)
UPDATE
Here is some more context regarding your code. The constructor of the Banana type is actually incorrect.
It's not possible to call new on a type instance. What you're actually trying to do is instantiate an object of the passed eggplant parameter. There are multiple ways you can achieve that. But before going into details I recommend you to read about type constructors first.
Besides, it's a bit unclear what your intent is. What you're trying to do with the newly created instance. I would just assume for now that you're going to store that instance in some member variable, as follows:
public class Banana
{
private readonly object instance;
public Banana(Type eggplant, int feijoa)
{
this.instance = Activator.CreateInstancenew eggplant(feijoa, new object [] {feijoa});
}
}
Here I've used the Activator type which will create an instance of a given type if it'll find a matching constructor based on the parameters you've passed. Otherwise, an exception will be thrown.
While the above-mentioned approach would work, it's not ideal as it provides no type safety. So it would be great to use Generics here, but that is not possible with current code because of the requirement of having a constructor, which accepts a parameter. There is still a way to achieve that, but it'll require a lot of code changes, which is not directly related to your question. You can read more about Generics here.
While there are a lot of other options, I would ask whether it's really a requirement to have the design you've got here. Why not pass in the instances to the Banan class directly. To do that, you'll need to make sure there is a base class/interface, which all the potential parameters to the Banana constructor will extend. Here is an example you could go with:
class Program
{
void Apple()
{
List<Banana> apple = new List<Banana> { new Banana(new Cucumber(5)), new Banana(new Dates() { Feijoa = 6 }) };
}
}
class Banana
{
private readonly ICommon instance;
public Banana(ICommon instance)
{
this.instance = instance;
}
}
public interface ICommon
{
int Feijoa { get; set; }
}
class Cucumber : ICommon
{
public Cucumber(int feijoa)
{
this.Feijoa = feijoa;
}
public int Feijoa { get; set; }
}
class Dates : ICommon
{
public Dates()
{
}
public int Feijoa { get; set; }
}
Sorry, the provided context is not enought to be more specific. In the meantime, I tried to share as much as possible. I know, it may look scattered a bit.
Hope this helps.
Forgive me because I know my wording is terrible. I'll just give an example.
public class MainClass{
public int someVariable;
public List<HasAClass> cList = new List<HasAClass>();
addHasAClass(HasAClass c){
cList.Add(c);
}
}
public class HasAClass{
public HasAClass(){
//Modify someVariable in some way????
}
}
public class HasASubClass : HasAClass{
public ComposedClass(){
//Modify someVariable in some way???
}
}
I having trouble finding the right words for this questions but here is what I am trying to do:
I am creating an aid for an RPG similar to dungeons and dragons. Each character can have a variety of special abilitys which can effect the characters in some way (both negative and positive). I am trying do this with a variety of subclasses which store the pertinent info and get added to the character at varying points in time. What I can't figure out is how to modify the properties of the Character(I called it Main Class in my example) when instances of the HasA class are added to it.
The HasAClass needs a reference to the owning instance, so that it can ask the parent for values and update them when required...
public class HasAClass
{
private MainClass _mainClass;
public HasAClass(MainClass mainClass)
{
_mainClass = mainClass;
_mainClass.someVaraible = 42;
}
}
You then need to pass the owner reference into the constructor of the HasAClass when they are created. If this is not possible at the time of creating the instance then you would instead need to assign it as a property after it has been created. Such as inside the addHasAClass method.
I previously posted this, but I guess it was too verbose and irrelevant. My question is also like this. One poster in the second link said the answer (of why you can't do the code below) was a problem of design, specifically "bad use of inheritance". So I'd like to check this issue again with the experts at StackOverflow and see if this is really an issue of "bad inheritance" - but more importantly, how to fix the design.
Like the poster, I'm also confused about the Factory method and how I can apply it. It seems the factory method is for multiple concrete classes that have the exact same implementation as the abstract base class and do not add their own properties. But, as you will see below, my concrete classes build upon the abstract base class and add extra properties.
The Base Class We Build Upon:
public abstract class FlatScreenTV
{
public string Size { get; set; }
public string ScreenType { get; set; }
}
Extension Class Examples:
public class PhillipsFlatScreenTV : FlatScreenTV
{
// Specific to Phillips TVs. Controls the backlight intensity of the LCD screen.
public double BackLightIntensity { get; set; }
}
public class SamsungFlatScreenTV : FlatScreenTV
{
// Specific to Samsung TVs. Controls the time until the TV automatically turns off.
public int AutoShutdownTime { get; set; }
}
Let's say there are more extension classes for more brands of flat screen TVs. And then, let's say we stick them all into a generic List:
public static void Main()
{
List<FlatScreenTV> tvList = new List<FlatScreenTV>();
tvList.Add(new PhillipsFlatScreenTV());
tvList.Add(new SamsungFlatScreenTV());
tvList.Add(new SharpFlatScreenTV());
tvList.Add(new VizioFlatScreenTV());
FlatScreenTV tv = tvList[9]; // Randomly get one TV out of our huge list
}
The Problem:
I want to access the specific properties of whatever 'original' brand TV this variable belongs to. I know the brand because if I call tv.GetType(), it returns the correct 'original' type - not FlatScreenTV. But I need to be able to cast tv from FlatScreenTV back to its original type to be able to access the specific properties of each brand of flat-screen TVs.
Question #1: How can I dynamically cast that, properly - without makeshift hacks and huge if-else chains to brute-guess the 'original' type?
After browsing around similar design issues, most answers are: you can't. Some people say to look at the Factory Pattern, and others say to revise the design using interfaces, but I don't know how to use either to solve this problem.
Question #2: So, how should I design these classes so that I can access the original type's specific properties in the context above?
Question #3: Is this really bad inheritance?
Your design violates the "Liskov Substitution Principle". In other words, the code that deals with items from your list of FlatScreenTV shouldn't know or care what derived type is.
Say your code needs to create a custom remote control GUI. It might be enough to simply know the names and types of the properties of each TV to auto-generate the UI. In which case you could do something like this to expose the custom properties from the base class:
public abstract class FlatScreenTV
{
public FlatScreenTV()
{
CustomProperties = new Dictionary<string,object>();
}
public Dictionary<string,object> CustomProperties { get; private set; }
public string Size { get; set; }
public string ScreenType { get; set; }
}
public class PhillipsFlatScreenTV : FlatScreenTV
{
public PhillipsFlatScreenTV()
{
BackLightIntensity = 0;
}
// Specific to Phillips TVs. Controls the backlight intensity of the LCD screen.
public double BackLightIntensity
{
get { return (double)CustomProperties["BackLightIntensity"]; }
set { CustomProperties["BackLightIntensity"] = value; }
}
}
public class SamsungFlatScreenTV : FlatScreenTV
{
public SamsungFlatScreenTV()
{
AutoShutdownTime = 0;
}
// Specific to Samsung TVs. Controls the time until the TV automatically turns off.
public int AutoShutdownTime
{
get { return (int)CustomProperties["AutoShutdownTime"]; }
set { CustomProperties["AutoShutdownTime"] = value; }
}
}
If you really do need to be working directly with the derived types, then you should instead consider moving to a plugin based architecture. For example, you might have a factory method like this:
IRemoteControlGUI GetRemoteControlGUIFor(FlatScreenTV tv)
which would scan your plugins and find the one that knew how to build the UI for the particular type of FlatScreenTV you passed in. This means that for every new FlatScreenTV you add, you also need to create a plugin that knows how to make its remote control GUI.
Factory Pattern would be the best way to go
I can offer a partial answer:
Firstly read up on Liskov's Substitution Principle.
Secondly you are creating objects that inherit from FlatScreenTV, but apparently for no purpose as you want to refer to them by their SubType (SpecificTVType) and not their SuperType (FlatScreenTV) - This is bad use of Inheritance as it is NOT using inheritance lol.
If your code wants to access properties particular to a given type, then you really want this code encapsulated within that type. Otherwise everytime you add a new TV type, all the code that handles the TV list would need to be updated to reflect that.
So you should include a method on FlatScreenTV that does x, and override this in TV's as required.
So basically in your Main method above, instead of thinking I want to be dealing with TVTypeX, you should always refer to the basetype, and let inheritance and method overriding handle the specific behaviour for the subtype you are actually dealing with.
Code eg.
public abstract class FlatScreenTV
{
public virtual void SetOptimumDisplay()
{
//do nothing - base class has no implementation here
}
}
public class PhilipsWD20TV
{
public int BackLightIntensity {get;set;}
public override void SetOptimumDisplay()
{
//Do Something that uses BackLightIntensity
}
}
"the factory method is for multiple concrete classes that have the exact same implementation as the abstract base class [interface] and do not add their own properties."
No, speaking more practical, than theorical, the factory method can provide you with objects of concrete classes, in which the concrete classes, must have some common methods and interfaces, but, also some additional specific attributes.
Sometimes I use a method that creates the same class object every time I called, and I need to call it several times, and sometimes I use a method that create several different class objects, and that maybe be confusing, maybe another question.
And, your further comment about a switch sentence, with many options, when using the factory pattern, you usually provide an identifier for the concrete class / concrete object. This can be a string, an integer, an special type id, or an enumerated type.
You could use an integer / enum ID instead, and use a collection to lookup for the concrete class.
You can still leverage a factory. The point of a factory IMO is to put all the heavy lifting of constructing your various TVs in one place. To say categorically "a factory is for multiple concrete classes that have the exact same implementation as the abstract base class" is forgetting about polymorphism.
There is no law that says you cannot use a factory pattern because the sub classes declare unique properties and methods. But the more you can make use of polymorphism, the more a factory pattern makes sense. Also as a general guideline, IMHO, the more complexity that must go into constructing from the base the better off you are in the long run using a factory because you are "encapsulating change" - that is, constructing concrete classes is likely to change due to differing requirements and inherent construction complexity (a design analysis decision, to be sure) . And that change is in a single class - the factory.
Try this: Define everything in the abstract class and then for a given TV subclass either write concrete-specific code, and for those that don't apply write some standard "I don't do that" code.
Think about all the things your TVs do in generic terms: turn on, turn off, etc. Write a virtual method shell in the base class for all the generic things a TV does - this is a simple example of the template method pattern by the way. Then override these in the concrete classes as appropriate.
There are other things you can do in the base class to make it more fundgeable (that's a technical term meaning "reference subclasses as the base class, but do sub-classy things").
Define delegate methods (very powerful yet under-utilized)
use params[] for dynamic method parameter lists
Make Property delegates
Static methods
Declare Properties and methods "abstract" - forces sub-class implementation, vis-a-vis "virtual"
Hide inherited stuff in the sub class (generally using "new" keyword to communicate that it's on purpose)
If construction parameters are numerous or complex, create a class specifically designed to pass configuration to the factory's build method.
public class TVFactory {
public TV BuildTV(Brands thisKind) {
TV newSet;
switch (thisKind) {
case Brands.Samsung :
Samsung aSamsungTV = new Samsung();
aSamsungTV.BacklightIntensity = double.MinVal;
aSamsungTV.AutoShutdownTime = 45; //oops! I made a magic number. My bad
aSamsungTV.SetAutoShutDownTime = new delegate (newSet.SetASDT);
newSet = aSamsungTV;
break;
. . .
} // switch
}
//more build methods for setting specific parameters
public TV BuildTV (Brands thisKind, string Size) { ... }
// maybe you can pass in a set of properties to exactly control the construction.
// returning a concrete class reference violates the spirit of object oriented programming
public Sony BuildSonyTV (...) {}
public TV BuildTV (Brands thisKind, Dictionary buildParameters) { ... }
}
public class TV {
public string Size { get; set; }
public string ScreenType { get; set; }
public double BackLightIntensity { get; set; }
public int AutoShutdownTime { get; set; }
//define delegates to get/set properties
public delegate int GetAutoShutDownTime ();
public delegate void SetAutoShutDownTime (object obj);
public virtual TurnOn ();
public virtural TurnOff();
// this method implemented by more than one concrete class, so I use that
// as an excuse to declare it in my base.
public virtual SomeSonyPhillipsOnlything () { throw new NotImplementedException("I don't do SonyPhillips stuff"); }
}
public class Samsung : TV {
public Samsung() {
// set the properties, delegates, etc. in the factory
// that way if we ever get new properties we don't open umpteen TV concrete classes
// to add it. We're only altering the TVFactory.
// This demonstrates how a factory isolates code changes for object construction.
}
public override void TurnOn() { // do stuff }
public override void TurnOn() { // do stuff }
public void SamsungUniqueThing () { // do samsung unique stuff }
internal void SetASDT (int i) {
AutoShutDownTime = i;
}
}
// I like enumerations.
// No worries about string gotchas
// we get intellense in Visual Studio
// has a documentation-y quality
enum Brands {
Sony
,Samsung
,Phillips
}
All I need is a way to make a property of one class only 'settable' from one other class (a sort of manager class).
Is this even possible in c#?
My colleague 'reliably' informs me that I have a design flaw, but I feel I should at least ask the community before I concede defeat!
No, it's not really possible to do this in any clean way in C#. You probably have a design flaw ;-)
You can use the internal modifier, which lets all types in the same assembly access the data (or nominated assemblies if using [InternalsVisibleTo] - but no: there is no friend equivalent in C#.
For example:
public string Foo {get; internal set;}
You have a design flaw. Also, don't be paranoid about data hiding. Here's 3.5's way to do it:
class Program
{
static void Main(string[] args)
{
Managed m = new Managed();
Console.WriteLine(m.PrivateSetter);
m.Mgr.SetProperty("lol");
Console.WriteLine(m.PrivateSetter);
Console.Read();
}
}
public class Managed
{
private Manager _mgr;
public Manager Mgr
{
get { return _mgr ?? (_mgr = new Manager(s => PrivateSetter = s)); }
}
public string PrivateSetter { get; private set; }
public Managed()
{
PrivateSetter = "Unset";
}
}
public class Manager
{
private Action<string> _setPrivateProperty;
public Manager(Action<string> setter)
{
_setPrivateProperty = setter;
}
public void SetProperty(string value)
{
_setPrivateProperty(value);
}
}
Here's how we'd do it in pre-lambda days:
public class Managed
{
private Manager _mgr;
public Manager Mgr
{
get { return _mgr ?? (_mgr = new Manager(this)); }
}
public string PrivateSetter { get; private set; }
public Managed()
{
PrivateSetter = "Unset";
}
public class Manager
{
public void SetProperty(string value)
{
m.PrivateSetter = value;
}
private Managed m;
public Manager(Managed man)
{
m = man;
}
}
}
The best way to do it would be:
/// <summary>
/// Gets or sets foo
/// <b>Setter should only be invoked by SomeClass</b>
/// </summary>
public Object Foo
{
get { return foo; }
set { foo = value; }
}
When you have some complex access or inheritance restriction, and enforcing it demands too much complexity in the code, sometimes the best way to do it is just properly commenting it.
Note however that you cannot rely on this if this restriction has some security implications, as you are depending on the goodwill of the developer that will use this code.
You cannot do that on that way, but you can access a property's setter method from a derived class, so you can use inheritance for the purpose. All you have to do is to place protected access modifier. If you try to do so, your colleague is right :). You can try doing it like this:
public string Name
{
get{ return _name; }
protected set { _name = value; }
}
keep in mind that the set method of the property is only accessible from the derived class.
Or you could have these two classes in an assembly alone and have the setter as internal. I would vote up for the design flaw though, unless the previous answer by milot (inheriting and protected) makes sense.
You could do:
public void setMyProperty(int value, Object caller)
{
if(caller is MyManagerClass)
{
MyProperty = value;
}
}
This would mean that you could use a 'this' pointer from the calling class. I would question the logic of what you're attempting to achieve, but without knowing the scenario I can't advise any futher. What I will say is this: if it is possible to refactor your code to make it clearer, then it is often worthwhile doing so.
But this is pretty messy and certinly NOT fool-proof ... you have been warned!
Alternativly...
You could pass a delegate from the Class with the Property (Class A) to the Manager Class (Class B). The delegate can refer to a private function within A to allow B to call that delegate as any normal function. This precludes that A knows about B and potentially that A is created before B. Again... messy and not fool-proof!
You can achieve to this by making a Public property in your "settable class" that will inherit from the real class that will have a protected property... this way only the inherit class can SET and not class that doesn't inherit. But the drawback is that you will require to have an inherit class...
Reflection, though I would agree that having to do this just to get around an access modifier is probably an indication of a bad design.
public class Widget
{
private int count;
public int Count
{
get { return this.count; }
private set { this.count = value; }
}
}
public static class WidgetManager
{
public static void CatastrophicErrorResetWidgetCount( Widget widget )
{
Type type = widget.GetType();
PropertyInfo info = type.GetProperty("Count",BindingFlags.Instance|BindingFlags.NonPublic);
info.SetValue(widget,0,null);
}
}
The reason this is a design flaw is because it seems muddled between the scope of the two objects.
The properties of a class should be accessible in the context of that class, at least internally.
It sounds like the settable property on your item class is really a property of the manager class.
You could do something similar to what you want by closely coupling the two classes:
public class MyItem {
internal MyItemManager manager { get;set; }
public string Property1 {
get { return manager.GetPropertyForItem( this ); }
}
}
Unfortunately this isn't great design either.
What your looking for is what C++ calls a Friend class but neither c# or vb has this functionality. There is a lot of debate as to the merit of such functionality since it almost encourages very strong coupling between classes. The only way you could implement this in c# would be with reflection.
If your goal is to have a class Foo let some property (e.g. Bar, of type Biz) to be changed by some other object, without exposing it publicly, a simple way to do that is to have an instance of Foo which is supposed to be changeable by some other object to pass that other object an Action<Biz> which points to a private method that changes Bar to the passed-in value. The other object may use that delegate to change the Bar value of the object that supplied it.
If one wishes to have give all instances of some type Woozle the ability to set the Bar value of any instance of Foo, rather than exposing such abilities on a per-instance basis, one may require that Woozle have a public static method Woozle.InstallFooBarSetter which takes a parameter of type Action<Foo, Biz> and one of type Object. Foo should then have a static method WoozleRequestBarSetter which takes an Object, and passes it to Woozle.InstallFooBarSetter along with an Action<Foo,Biz>. The class initializer for Woozle should generate a new Object, and pass it to Foo.RequestBarSetter; that will pass the object to Woozle.InstallFooBarSetter along with a delegate. Woozle can then confirm that the passed-in object is the one that it generated, and--if so--install the appropriate delegate. Doing things this way will ensure that nobody but Woozle can get the delegate (since the delegate is only passed to Woozle.InstallFooBarSetter), and Woozle can be sure its delegate comes from Foo (since nobody else would have access to the object that Woozle created, and Woozle.InstallFooBarSetter won't do anything without it).
if it is a design flaw depends on what you want to do. You could use the StackTrace class from System.Diagnostics to get the Type of the class setting your property and then compare to the type you want to allow setting yor property..but maybe there are better ways for performing something like this (e.g. boxing)