Relatively minor question about something I am missing here,
I am attempting to do a simple GetSet in C# to get the hang of the syntax but appear to have missed something as all that is printed is GetSet.Role and not the actual attributes being assigned.
Have I just worded something wrong? Apologies for the minor question but any help is appreciated.
namespace GetSet
{
class Program
{
static void Main(string[] args)
{
Role Mage = new Role("Staff", "Robes", "Magic affinity");
Role Warrior = new Role("Sword", "Platebody", "Strength");
Role Rogue = new Role("Needle", "Leather", "Cunning");
Console.WriteLine(Mage);
Console.WriteLine(Warrior);
Console.WriteLine(Rogue);
//stop the program from closing
Console.ReadLine();
}
}
}
and the following is my class:
namespace GetSet
{
class Role
{
//private variables
private string weapon;
private string armour;
private string passive;
//public structs
public Role(string aWeapon, string aArmour, string aPassive)
{
weapon = aWeapon;
armour = aArmour;
passive = aPassive;
}
//Getters and Setters for above private variables
public string Weapon
{
get { return weapon; }
set { weapon = value;}
}
public string Armour
{
get { return armour; }
set { armour = value;}
}
public string Passive
{
get { return passive; }
set { passive = value;}
}
}
}
Add a ToString() to your Role class and set it return whatever you want:
public override string ToString()
{
return $"Weapon: {weapon}, Armor: {armor}, Passive: {passive}";
}
You need to override the ToString method on the GetSet class.
Something like:
public override string ToString()
{
return $"{weapon}/{armour}/{passive}";
}
Update
You can simplyfy your Role class.
internal class Role
{
public Role(string weapon, string armour, string passive)
{
Weapon = weapon;
Armour = armour;
Passive = passive;
}
public string Weapon { get; }
public string Armour { get; }
public string Passive { get; }
public override string ToString()
{
return $"{Weapon}/{Armour}/{Passive}";
}
}
Re: vasily.sib's comment.
If you need to change the properties after object creation then simply change
public string Passive { get; }
to
public string Passive { get; set; }
As other answers lacks of getters/setters syntax examples, I will post my.
namespace GetSet
{
public class Role
{
// private backing field
private string _weapon;
// properties can have getters and setters, that contains some logic
public string Weapon
{
get { return _weapon; }
set { if (_weapon != vale) _weapon = value; }
}
// there is an auto-getters/setters
// in this case, backing field is handled by .Net CLR
public string Armour { get; set; }
// getters and setters may have different access level
// also, note property initializer '= "John";' - this will set property value
// to "John" right before constructor invocation
public string Name { get; private set; } = "John";
// properties also can be readonly, so they can be setted only in constructors
public string Passive { get; }
// public constructor
public Role(string passive)
{
Passive = passive;
}
public void ChangeName(string newName)
{
Name = newName; // setting property through private setter
}
// I believe, that this method shouldn't be used to represent object as string
// At least, I think, you should never relay on it's return value, BUT it ups to you
public overide string ToString() => Name;
}
}
Also, as you can see, I'm not setting publicly available properties (properties with public setters, Weapon and Armour) in consturctors, because I can initialize them along with constructing Role object, like this:
var mage = new Role("Magic affinity") { Weapon = "Staff", Armor = "Robes" };
mage.ChangeName("John, Doe");
As said before, I beleive that it is not relay on object itself, how it will look in string. I thinking so, because if you for some reasons need to represent same object as different strings in different places of your code - this will cause troubles. So instead of this:
// this will call .ToString() method
Console.WriteLine(mage);
// output: John, Doe
I suggest this:
// represent object as you need
Console.WriteLine($"{mage.Name} - walks in {mage.Armour}, beats with {mage.Weapon}");
// output: John, Doe - walks in Robes, beats with Staff
Related
I am searching for a solution where i can ask a model if a property has changed. But i want to prevent to write own setter methods for all models and all their properties.
I want to use this to automatically generate a update queries based models and there changed properties. But if my model has a boolean property Test which is by default false, then i can't differentiate if the value is from the request payload or if it is the default value.
I already saw the INotifyPropertyChanged Implementation but there i have to write a setter for all properties too.
public class Main
{
public static void main()
{
var person = new Person();
Console.WriteLine(person.HasChanged("Firstname")); // false
Console.WriteLine(person.HasChanged("Lastname")); // false
Console.WriteLine(person.HasChanged("LikesChocolate")); // false
person.Firstname = "HisFirstname";
person.LikesChocolate = true;
Console.WriteLine(person.HasChanged("Firstname")); // true
Console.WriteLine(person.HasChanged("Lastname")); // false
Console.WriteLine(person.HasChanged("LikesChocolate")); // true
}
}
public class Person : BaseModel
{
public string Firstname { get; set; }
public string Lastname { get; set; }
public bool LikesChocolate { get; set; }
}
public class BaseModel
{
public bool HasChanged(string propertyName)
{
// ...
}
}
I'd probably reuse the idea from WPF with their INotifyPropertyChanged pattern and simplify it a bit for the current needs. However, it resolves the question only partially, as you still need to write setters. But at least, you don't need to manage each property on its own.
So, the solution will be something like this:
void Main()
{
var person = new Person();
Console.WriteLine(person.HasChanged(nameof(Person.FirstName))); // false
Console.WriteLine(person.HasChanged(nameof(Person.LastName))); // false
Console.WriteLine(person.HasChanged(nameof(Person.LikesChocolate))); // false
person.FirstName = "HisFirstname";
person.LikesChocolate = true;
Console.WriteLine(person.HasChanged(nameof(Person.FirstName))); // true
Console.WriteLine(person.HasChanged(nameof(Person.LastName))); // false
Console.WriteLine(person.HasChanged(nameof(Person.LikesChocolate))); // true
}
public class Person : ChangeTrackable
{
private string _firstName;
private string _lastName;
private bool _likesChocolate;
public string FirstName
{
get { return _firstName; }
set { SetProperty(ref _firstName, value); }
}
public string LastName
{
get { return _lastName; }
set { SetProperty(ref _lastName, value); }
}
public bool LikesChocolate
{
get { return _likesChocolate; }
set { SetProperty(ref _likesChocolate, value); }
}
}
public class ChangeTrackable
{
private ConcurrentDictionary<string, bool> _changes =
new ConcurrentDictionary<string, bool>();
public bool HasChanged(string propertyName)
{
return _changes.TryGetValue(propertyName, out var isChanged)
? isChanged : false;
}
public void ResetChanges()
{
_changes.Clear();
}
protected void SetProperty<T>(
ref T storage, T value, [CallerMemberName] string propertyName = "")
{
if (!Equals(storage, value))
{
_changes[propertyName] = true;
}
}
}
The ChangeTrackable tracks if property was changed and does it without any reflection that guarantees high performance. Note, that with this implementation you need to call ResetChanges if you initialize property with some actual values after constructing the object. Drawback is that you need to write each property with its backing field and call SetProperty. On the other side, you decide what to track, that could be handy in the future in your application. Also we don't need to write property as strings (thanks to compile-time CallerMemberName and nameof) that simplifies refactorings.
INotifyPropertyChanged is the established practice for this type of requirement. Part of keeping your code maintainable is by keeping it predictable and by adopting best practices and patterns.
An alternative, which I wouldn't recommend, would be to use reflection to iterate over all of your properties and dynamically add a property changed event handler. This handler could then set a boolean flag which can be returned by your HasChanges method. Please refer to this for a staring point: AddEventHandler using reflection
I would recommend avoiding unnecessary complexity though and stick with PropertyChanged notifications in your setters.
As followup for my comment a proof of concept (online):
using System.Reflection;
public class HasChangedBase
{
private class PropertyState
{
public PropertyInfo Property {get;set;}
public Object Value {get;set;}
}
private Dictionary<string, PropertyState> propertyStore;
public void SaveState()
{
propertyStore = this
.GetType()
.GetProperties()
.ToDictionary(p=>p.Name, p=>new PropertyState{Property = p, Value = p.GetValue(this)});
}
public bool HasChanged(string propertyName)
{
return propertyStore != null
&& propertyStore.ContainsKey(propertyName)
&& propertyStore[propertyName].Value != propertyStore[propertyName].Property.GetValue(this);
}
}
public class POCO : HasChangedBase
{
public string Prop1 {get;set;}
public string Prop2 {get;set;}
}
var poco = new POCO();
poco.Prop1 = "a";
poco.Prop2 = "B";
poco.SaveState();
poco.Prop2 = "b";
poco.HasChanged("Prop1");
poco.HasChanged("Prop2");
Be aware, that reflection may reduce the performance of your application when used extensively.
I'm about to design a class that more often then not will contain a reference to a Null value. It reminded me of nullable Datetime which has a boolean value to indicate if there is an actual value stored.
DateTime? dt = new DateTime?();
if(dt.HasValue)
{
//DoStuff
}
Is it a good coding practice to design a class as follows?
class Computer
{
public string Name;
public string ID;
//...
public bool IsHiveMind;
public HiveMindInfo RegInfo;
}
class HiveMindInfo
{
string SecretLocation;
int BaudRate;
int Port;
}
...and to use it...
Computer aComputer = GetComputer(...);
if(aComputer.IsHiveMind)
{
Network.DoHostileTakeOver(aComputer); //!
}
How about this code below?
It seems you can remove IsHiveMind variable since HiveMindInfo variable has the same meaning by checking its null or not.
class Computer
{
public string Name;
public string ID;
public HiveMindInfo RegInfo;
}
class HiveMindInfo
{
string SecretLocation;
int BaudRate;
int Port;
}
Computer aComputer = GetComputer(...);
if (aComputer != null && aComputer.RegInfo != null)
{
Network.DoHostileTakeOver(aComputer);
}
To answer your question, you could implement the code as proposed.
An alternative would be to consider the following design patterns:
Proxy Design Pattern
Strategy Design Pattern
Sample Code
interface ITakeOverStrategy
{
void Execute();
}
class KevinFlynnHackerStrategy : ITakeOverStrategy
{
public void Execute()
{
// a nod to Tron
}
}
class NeoHackerStrategy: ITakeOverStrategy
{
private readonly HiveMindInfo _hiveMindInfo;
public NeoHackerStrategy(HiveMindInfo info)
{
_hiveMindInfo = info;
}
public void Execute()
{
// Mr. Anderson!
}
}
// This is a surrogate class.
// ... The value returned by String.Empty is often used as a surrogate.
class IdleStrategy : ITakeOverStrategy
{
public void Execute()
{
// do nothing
}
}
class Computer
{
private readonly ITakeOverStrategy _takeoverStrategy ;
public Computer(ITakeOverStrategy strategy)
{
_takeoverStrategy = strategy;
}
public Subjugate()
{
// insert epic code here
_takeoverStrategy.Execute();
}
}
Then somewhere in your code you create an instance of Computer with the appropriate strategy:
var info = new HiveMindInfo();
// update instance parameters
var computer = new Computer(new NeoHackerStrategy(info));
computer.Subjugate();
UPDATES
August 13th, 2015 # 10:13 EST
My comment about structs is not within the scope of the original question, and has been removed:
If your classes are only going to contain fields/properties then I would consider converting them into struct.
Just add ? to your object:
class Computer
{
public string Name;
public string ID;
//...
public HiveMindInfo? RegInfo;
}
struct HiveMindInfo
{
string SecretLocation;
int BaudRate;
int Port;
}
And then check it exactly as you did with datetime:
Computer aComputer = GetComputer(...);
if (aComputer.RegInfo.HasValue)
{
// Do something
}
I'm having trouble writing up some code. I'm not too sure where and how to write up the constructors and the accessors.
The activity I have to do is this:
Write 3 derived classes to allow a user to enter the details of three types of Vehicles with their attributes.
• Car (make, model, year, bodyType)
• Airplane (make, model, year, noEngines, engineType)
• Boat (make, model, year, length, hullType)
The 4th class is the base class Vehicle which contains the shared attributes and methods
Make all attributes either private (in derived classes) or protected (in base class) and write accessor methods for each attribute.
Write 2 constructors for each derived class. One with no arguments and the other which accepts the values of the attributes in the derived class as arguments.
Write a Console Application called Fleet.cs which creates and displays 2 of each Vehicle type
My code so far is as follows:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication5
{
class Vehicle
{
static void Main(string[] args)
{
}
class Car
{
protected string make
{
get
{
return make;
}
set
{
make = value;
}
}
protected string model
{
get
{
return model;
}
set
{
model = value;
}
}
protected int year
{
get
{
return year;
}
set
{
year = value;
}
}
protected string bodyType
{
get
{
return bodyType;
}
set
{
bodyType = value;
}
}
public bool isInitialized;
public Car()
{
isInitialized = true;
}
}
}
class Airplane
{
protected string make
{
get
{
return make;
}
set
{
make = value;
}
}
protected string model
{
get
{
return model;
}
set
{
model = value;
}
}
protected int year
{
get
{
return year;
}
set
{
year = value;
}
}
protected int numEngines
{
get
{
return numEngines;
}
set
{
numEngines = value;
}
}
protected int engineType
{
get
{
return engineType;
}
set
{
engineType = value;
}
}
}
class Boat
{
protected string make
{
get
{
return make;
}
set
{
make = value;
}
}
protected string model
{
get
{
return model;
}
set
{
model = value;
}
}
protected string year
{
get
{
return year;
}
set
{
year = value;
}
}
protected string length
{
get
{
return length;
}
set
{
length = value;
}
}
protected string hullType
{
get
{
return hullType;
}
set
{
hullType = value;
}
}
}
}
First part the OOP principles
Classes:
A class is a construct that enables you to create your own custom
types by grouping together variables of other types, methods and
events. A class is like a blueprint. It defines the data and behavior
of a type. If the class is not declared as static, client code can use
it by creating objects or instances which are assigned to a variable.
The variable remains in memory until all references to it go out of
scope. At that time, the CLR marks it as eligible for garbage
collection. If the class is declared as static, then only one copy
exists in memory and client code can only access it through the class
itself, not an instance variable. For more information, see Static
Classes and Static Class Members (C# Programming Guide). Unlike
structs, classes support inheritance, a fundamental characteristic of
object-oriented programming. For more information, see Inheritance (C#
Programming Guide).
Also objects are instances of classes.
Inheritance:
Inheritance, together with encapsulation and polymorphism, is one of
the three primary characteristics (or pillars) of object-oriented
programming. Inheritance enables you to create new classes that reuse,
extend, and modify the behavior that is defined in other classes. The
class whose members are inherited is called the base class, and the
class that inherits those members is called the derived class. A
derived class can have only one direct base class. However,
inheritance is transitive. If ClassC is derived from ClassB, and
ClassB is derived from ClassA, ClassC inherits the members declared in
ClassB and ClassA.
Derived class:
A class that was created based on a previously existing class (i.e., base class). A derived class inherits all of the member variables and methods of the base class from which it is derived.
Also called a derived type.
Method:
A method (or message) in object-oriented programming (OOP) is a
procedure associated with an object class. An object is made up of
behavior and data. Data is represented as properties of the object and
behavior as methods. Methods are also the interface an object presents
to the outside world. For example a window object would have methods
such as open and close. One of the most important capabilities that a
method provides is method overriding. The same name (e.g., area) can
be used for multiple different kinds of classes. This allows the
sending objects to invoke behaviors and to delegate the implementation
of those behaviors to the receiving object. For example an object can
send an area message to another object and the appropriate formula
will be invoked whether the receiving object is a rectangle,circle,
triangle, etc.
Attributes and properties:
"Fields", "class variables", and "attributes" are more-or-less the
same - a low-level storage slot attached to an object. Each language's
documentation might use a different term consistently, but most actual
programmers use them interchangeably. (However, this also means some
of the terms can be ambiguous, like "class variable" - which can be
interpreted as "a variable of an instance of a given class", or "a
variable of the class object itself" in a language where class objects
are something you can manipulate directly.)
"Properties" are, in most languages I use, something else entirely -
they're a way to attach custom behaviour to reading / writing a field.
(Or to replace it.)
So if you want to categorize them they are OOP(Object Oriented Programming) principles.
Second part:
Write a Console Application called Fleet.cs which creates and displays
2 of each Vehicle type.
So one way of doing this is creating vehicles as hardcoded. The other way is to ask user for vehicle details with Console.Readline(). Main method could look something like this.
static void Main(string[] args)
{
Vehicle v1 = new Vehicle { Make = "test1", Model = "model1", Year = 1996 };
Vehicle v2 = new Vehicle { Make = "test2", Model = "model2", Year = 1997 };
Console.WriteLine(v1);
Console.WriteLine(v2);
...
}
And then you would override the ToString() method for each class. Like this:
public override string ToString()
{
return string.Format("Vehicle is {0} and of model {1} and is made in {2}.", make, model, year);
}
Here you also can use base.ToString() to get the data of upper (base) class in the derivided class.
EDIT 1: User input:
So if you want the user input you could make program like this:
static void Main(string[] args)
{
//input
Vehicle v1 = new Vehicle();
Console.Write("Enter the make of 1st vehicle: ");
v1.Make = Console.ReadLine();
Console.Write("Enter the model of 1st vehicle: ");
v1.Model = Console.ReadLine();
Console.WriteLine("Enter the year of manufacturing for 1st vehicle:");
v1.Year = int.Parse(Console.ReadLine());
//output
Console.WriteLine("The data for 1st vehicle: ");
Console.WriteLine(v1);
...
}
Even better would be to create Input method in the class and calling it from Main program. So code would not be repeating itself.
Finished program
Vehicle.cs
using System;
class Vehicle
{
string make, model;
int year;
public string Make { get { return make; } set { make = value; } }
public string Model { get { return model; } set { model = value; } }
public int Year { get { return year; } set { year = value; } }
public Vehicle()
{
make = model = "Unknown";
year = 0;
}
public Vehicle(string make, string model, int year)
{
this.make = make;
this.model = model;
this.year = year;
}
public virtual void GetFromInput()
{
Console.Write("Enter the make of vehicle: ");
Make = Console.ReadLine();
Console.Write("Enter the model of vehicle: ");
Model = Console.ReadLine();
Console.WriteLine("Enter the year of manufacturing for vehicle: ");
Year = int.Parse(Console.ReadLine());
}
public override string ToString()
{
return string.Format("Vehicle is {0} and of model {1} and is made in {2}.", make, model, year);
}
}
Car.cs
using System;
class Car : Vehicle
{
string bodyType;
public string BodyType { get { return bodyType; } set { bodyType = value; } }
public Car() : base()
{
bodyType = "Unknown";
}
public Car(string make, string model, int year, string bodyType) : base(make, model, year)
{
this.bodyType = bodyType;
}
public override void GetFromInput()
{
base.GetFromInput();
Console.Write("Enter body type for the car: ");
BodyType = Console.ReadLine();
}
public override string ToString()
{
return base.ToString() + string.Format("This vehicle is a car with body type of {0}.", BodyType);
}
}
Airplane.cs
using System;
class Airplane : Vehicle
{
int noEngines;
string engineType;
public int NumberOfEngines{ get { return noEngines; } set { noEngines = value; } }
public string EngineType { get { return engineType; } set { engineType = value; } }
public Airplane() : base()
{
noEngines = 0;
engineType = "Unknown";
}
public Airplane(string make, string model, int year, int noEngines, string engineType) : base(make, model, year)
{
this.noEngines = noEngines;
this.engineType = engineType;
}
public override void GetFromInput()
{
base.GetFromInput();
Console.Write("Enter the number of engines on an airplane: ");
NumberOfEngines = int.Parse(Console.ReadLine());
Console.Write("Enter the engine type for the airplane: ");
EngineType = Console.ReadLine();
}
public override string ToString()
{
return base.ToString() + string.Format("This vehicle is an airplane with {0} engines and engine type of {1}.", NumberOfEngines, EngineType);
}
}
Boat.cs
using System;
class Boat : Vehicle
{
int length;
string hullType;
public int Length { get { return length; } set { length = value; } }
public string HullType { get { return hullType; } set { hullType = value; } }
public Boat() : base()
{
length = 0;
hullType = "Unknown";
}
public Boat(string make, string model, int year, int length, string hullType) : base(make, model, year)
{
this.length = length;
this.hullType = hullType;
}
public override void GetFromInput()
{
base.GetFromInput();
Console.Write("Enter the length of the boat: ");
Length = int.Parse(Console.ReadLine());
Console.Write("Enter the hull type for the boat: ");
HullType = Console.ReadLine();
}
public override string ToString()
{
return base.ToString() + string.Format("This vehicle is a boat with length of {0} and hull type of {1}.", Length, HullType);
}
}
Fleet.cs
using System;
class Fleet
{
static void Main(string[] args)
{
Vehicle v1 = new Vehicle();
v1.GetFromInput();
Console.WriteLine(v1);
//... for the other vehicles
}
}
This can be achieved using class inheritance.
Each of your vehicle classes, need to inherit a common class that implements functionality need by 'all' vehicles, This class (Vehicle receptively), can then be used in C# to identify any type of vehicle class/type.
Instead of having a several classes where each class is solely responsible for a type of vechile, you can abstract out common functionality needed by each vehicle, and implement a class that exposes these common relationships:
using System;
public namespace CodeSpace {
public class Vehicle {
public Vehicle(Type type, string make, string model) {
Model = model;
Make = make;
Type = type;
}
public Type VehicleType { get; private set; }
public string Make { get; set; }
public string Model { get; set; }
}
public class Airplane : Vehicle {
public class Airplane(string make, string model) : base(typeof(Airplane), make, model) {
}
}
public class Boat : Vehicle {
public class Boat(string make, string model) : base(typeof(Boat), make, model) {
}
}
public class Car : Vehicle {
public class Car(string make, string model) : base(typeof(Car), make, model) {
}
}
class Program {
public static void Main(params string[] args ) {
var vehicles = new List<Vehicle>() {
new Boat("Canoe", "X2") as Vehicle,
new Boat("Raft", "A") as Vehicle,
new Car("Ford", "T") as Vehicle,
new Airplane("BMW", "Idk") as Vehicle,
};
foreach(var v in vehicles) {
Console.WriteLine(v.VehicleType.FullName);
}
}
}
}
Now all of your vehicles can be identified using one class that exposes all vehicles through a common interface.
I have class which have too many related calculated properties.
I have currently kept all properties are read only.
some properties need long calculation and it is called again when its related properties are needed.
How can create this complex object .Also i want these properties should not be set from external code. I need show hide as i am binding properties for UI. Also i think order is also important.
My Class is something like
public string A
{
get
{
return complexMethod();
;
}
}
public string B
{
get
{
if (A == "value")
return "A";
else return "B";
;
}
}
public bool ShowHideA
{
get
{
return string.IsNullOrEmpty(A);
;
}
}
public bool ShowHideB
{
get
{
return string.IsNullOrEmpty(B);
;
}
}
public string complexMethod()
{
string value = "";
// calculation goes here
return value;
}
}
Thanks
You need to use Lazy type provided by .net:
Lazy<YourType> lazy = new Lazy<YourType>();
Make your properties internal to not be set from external code.
Well tall order isn't it?
One of the coolest things about extension methods is you can use types. This is perfect for writing external programs to calculate property values. Start like this...
public static class XMLibrary
{
public static MC CalculateValues(this MC myclass)
{
//for each property calculate the values here
if (myclass.Name == string.Empty) myclass.Name = "You must supply a name";
if (myclass.Next == 0) myclass.Next = 1;
//when done return the type
return myclass;
}
}
public class MC
{
public string Name { get; set; }
public int Next { get; set; }
}
public class SomeMainClass
{
public SomeMainClass()
{
var mc = new MC { Name = "test", Next = 0 };
var results = mc.CalculateValues();
}
}
There are many other ways to do class validation on a model, for example dataannotations comes to mind, or IValidatableObject works too. Keeping the validation separate from the class is a good idea.
//Complex properites are simple
public class MyComplextClass{
public List<MyThings> MyThings {get;set;}
public List<FileInfo> MyFiles {get;set;}
public List<DateTime> MyDates {get;set;}
}
I am working with insurance and have two different policy types - motor and household, represented by two different classes, Motor and Household.
Both have several bits of data in common, so both would inherit from another class called Policy. When a user logs into the app, they could have either a motor or a household policy, so the app needs to display the generic information and the information unique to Motor or Household. To encapsulate all this, i have a response object that has both a Motor member and a Household member, as shown below:
public class Response
{
...
private MotorPolicy _motorPolicy;
private HouseholdPolicy _householdPolicy;
....
}
The code below should demonstrate:
if (response.PolicyType == Enumerations.PolicyType.Motor)
{
lblDescription.Text = response.MotorPolicy.Description;
lblReg.Text = response.MotorPolicy.Reg;
}
else
{
lblDescription.Text = response.HouseholdPolicy.Description;
lblContents.Text = response.HouseholdPolicy.Contents;
}
The MotorPolicy doesn't have Contents property and the HouseholdPolicy doesn't have a Reg property.
But I really want to simply do:
if (response.PolicyType == Enumerations.PolicyType.Motor)
{
lblDescription.Text = response.Policy.Description;
...
}
I have tried using generics, could couldn't find the right solution.
Your response only needs a Policy type, you can then store a MotorPolicy or HouseholdPolicy type into it.
Then your response just needs to check for data type
if (response.Policy is MotorPolicy) ....
Alternatively have an abstract method or a property returning data from an abstract method on the Policy type that is fully inplemented by the child classes and returns reg data or contents data as apporpriate.
Each Policy descendant (now you have two, you might have more in the future, right?) should have their own UI controls which "know" how to deal with the policy information. The same approach can be used for other things, such as a "controller" for policy objects etc.
The response can then be made generic:
public class Response<T> where T: Policy {
...
private T _policy;
....
}
Alternatively, you could have a more generic approach which uses reflection to display the information, but those are usually less "sexy" in their appearance and usability (think of the Property Grid in the VS designer).
public interface IPolicy
{
string Description { get; }
string Reg { get; }
string Contents { get; }
}
public class MotorPolicy : IPolicy
{
public string Description
{
get { return ...; }
}
public string Reg
{
get { return ...; }
}
public string Contents
{
get { return String.Empty; }
}
}
public class HousholdPolicy : IPolicy
{
public string Description
{
get { return ...; }
}
public string Reg
{
get { return String.Empty; }
}
public string Contents
{
get { return ...; }
}
}
public class Response
{
...
private IPolicy _policy;
....
}
Now you don't need an Enumeration to show which type you've implemented, you can just say
lblDescription.Text = response.Policy.Description;
lblReg.Text = response.Policy.Reg;
lblContents.Text = response.Policy.Contents;
Edit: Alternate solution
public interface IPolicy
{
string Description { get; }
}
public interface IHasReg
{
string Reg { get; }
}
public interface IHasContents
{
string Contents { get; }
}
public class MotorPolicy : IPolicy, IHasReg
{
public string Description
{
get { return ...; }
}
public string Reg
{
get { return ...; }
}
}
public class HouseholdPolicy : IPolicy, IHasContents
{
public string Description
{
get { return ...; }
}
public string Contents
{
get { return ...; }
}
}
public class Response
{
...
private IPolicy _policy;
....
}
This leaves you with more code in the calling function
lblDescription.Text = response.Policy.Description;
IHasReg hasReg = response.Policy as IHasReg;
if (hasReg != null) lblReg.Text = hasReg.Reg;
IHasContents hasContents = response.Policy as IHasContents;
if (hasContents != null) lblContents.Text = hasContents.Contents;
but is considerably more extensible than other options presented and complies with your desire to avoid functionality in the implementation which doesn't make sense.
One option is to add a member to Policy that synthesizes all the derived class' relevant properties to provide a summary:
public abstract class Policy {
public string Description { get; set; }
public abstract string Summary { get; }
}
public class MotorPolicy: Policy {
public override string Summary {
get { return this.Description + "\r\n" + this.Reg; }
}
}
public class HouseholdPolicy: Policy {
public override string Summary {
get { return this.Description + "\r\n" + this.Contents; }
}
}
This centralizes the logic and makes the user interface code simple:
label.Description.Text = response.Policy.Summary;
That basic implementation sacrifices the ability to format the subsections separately. You could overcome that by exposing the summary as a collection of strings:
public abstract IEnumerable<string> SummarySections { get; }
If you want to display the derived classes' details in fundamentally different ways, you'll have to embrace the conditional logic in the user interface layer (for example, you might list the household policy's contents in a table, but show a scanned image for the motor policy's registration).
Use the template pattern:
Create a base class called Policy with a virtual abstract get method to determine the description of the policy.
public abstract class Policy
{
protected virtual string GetDescription()
{
return string.Empty()
}
public string Description
{
get
{
return GetDescription();
}
}
}
public MotorPolicy : Policy
{
public override string GetDescription()
{
return ..... ////specific description implementation for MotorPolicy
}
}
public HouseHoldPolicy : Policy
{
public override string GetDescription()
{
return ..... ////specific description implementation for HouseholdPolicy
}
}
public class Response
{
...
private MotorPolicy _motorPolicy;
private HouseholdPolicy _householdPolicy;
private PolicyType _policyType;
....
public Policy Policy
{
get
{
if (_policyType== PolicyType.Motor)
{
return _motorPolicy;
}
if (_policyType== PolicyType.Household)
{
return _householdPolicy;
}
return null;
}
}
}
client code:
if (response.Policy != null)
{
lblDescription.Text = response.Policy.Description;
...
}
Let MotorPolicy and HouseholdPolicy derive from Policy and override the abstract get method from the base and create a specific implementation of it.
In the Response class just get the description.
The simplest solution would be to implement an interface with a description property and a "contents" property, and then in your motor policy class, create a dummy "contents" property which returns "reg".
Can your response contain either a MotorPolicy or a HouseholdPolicy or, can it contain one of each?
If you are dealing with one or the other then create a base type that both classes inherit that defines the common properties. When you output the common properties just cast the Policy as the base type and use that.
My immediate thought is to go for:
public abstract class Response
{
public abstract Policy Policy {get;}//can be used for stuff for dealing with all policies.
public static Response GetResponse(Policy policy)
{//factory method
if(policy is MotorPolicy)
return new MotorResponse((MotorPolicy)policy);
if(policy is HouseholdPolicy)
return new HouseholdResponse((HouseholdPolicy)policy);
throw new ArgumentException("Unexpected policy type");
}
}
public class MotorResponse : Response
{
private readonly MotorPolicy _motorPolicy;
public MotorResponse(MotorPolicy policy)
{
_motorPolicy = policy;
}
protected override Policy Policy
{
get { return _motorPolicy; }
}
// motor specific stuff
}
public class HouseholdResponse : Response
{
private readonly HouseholdPolicy _householdPolicy;
public HouseholdResponse(HouseholdPolicy policy)
{
_householdPolicy = policy;
}
protected override Policy Policy
{
get { return _householdPolicy; }
}
// household specific stuff
}
I would try something like this:
public class Response
{
public Policy SelectedPolicy {get;set;}
//I don't think you need these, but hard to
//say without seeing the rest of the code
...
private MotorPolicy _motorPolicy;
private HouseholdPolicy _householdPolicy;
....
}
then
lblDescription.Text = response.SelectedPolicy.Description;
if (SelectedPolicy is MotorPolicy)
lblReg.Text = ((MotorPolicy)response.SelectedPolicy).Reg;
else if (SelectedPolicy is HouseholdPolicy)
lblContents.Text = ((HouseholdPolicy)response.SelectedPolicy).Contents;
I would not put both Reg and Contents in the base class or interface. If I do what's the purpose of inheritance if all classes look the same? The only benefits I would get would be types, and that's not going to gain me much in this case.
maybe I don't understand the question but I would just use inheritence
define policy as
public class Policy
{
public string Description{ get; set;}
public string Details {get; set;}
}
public class MotorPolicy:Policy
{
public void SetReg(string reg)
{
base.Details = reg;
}
}
public class HousePolicy:Policy
{
public void SetContents(string contents)
{
base.Details = contents;
}
}
and call by
private void Form1_Load(object sender, EventArgs e)
{
MotorPolicy mp = new MotorPolicy();
mp.Description = "Motor";
SetForm(mp);
}
private void SetForm(Policy p)
{
lblDescription.Text = p.Description;
lblDetail.Text = p.Details;
//then if you still need specifics
if (p.GetType() == typeof(MotorPolicy))
{
MotorPolicy mp = p as MotorPolicy;
//continue assigning mp
}
else if (p.GetType() == typeof(HousePolicy))
{
HousePolicy hp = p as HousePolicy;
//continue assigning Hp
}
}
Note I put reg/contents as a field detail as they are both string types. If one was int vs string then they would have to be done separate.
define the Policy interface and implement it in your both the policy classes
Interface IPolicy{
int Reg {get;set;};
string Contents {get;set;};
}
MotorPolicy : Policy,IPolicy {
string IPolicy.Contents
{get;set;};
int IPolicy.Reg
{get;set;};
}
HouseholdPolicy : Policy , IPolicy {
string IPolicy.Contents
{get;set;};
int IPolicy.Reg
{get;set;};
}
Yours is a unique example of "Refactoring condition to Polymorphism" [Fowler].
And then your method should accept the proper object and do as below:
public void Update(IPolicy policy)
{
lblDescription.Text = policy.Description;
lblReg.Text = .Reg;
}
Well, I dislike abstract classes so I went with an interface for Policy
public interface IPolicy
{
string Description { get; set;}
void Display();
}
Then we inherit from it to create MotorPolicy
public class MotorPolicy : IPolicy
{
public string Description { get; set; }
public string Reg { get; set; }
public void Display()
{
Console.WriteLine(string.Format("Description: {0}", Description));
Console.WriteLine(string.Format("Reg: {0}", Reg));
}
}
Then for response I changed the Policy to a List in the off chance that you can have both or either. Now we've offloaded the handling of displaying the data to the specific policy itself.
public class Response
{
public List<IPolicy> Policies { get; set; }
public void Display()
{
Policies.ForEach(p => p.Display());
}
public void Display(Type t)
{
var policy = (from p in Policies
where p.GetType() == t
select p).FirstOrDefault();
policy.Display();
}
}
This could easily be changed to not use the List and we can get rid of the overloaded Display.