So I am reading that in .net it is not possible to inherit a second base class. How then Can you create an object that serves 2 functions from 2 classes? For example I have an object that I want to be a tool and a weapon. The first is public class SmithHammer : BaseTool the second would look like public class SmithHammer : BaseBashing The 2 classes BaseTool and BaseBashing can be used for the same item just not at the same time apparently. As a weapon I have it coded this way to call on the base class BaseBashing.
{
[FlipableAttribute( 0x13E3, 0x13E4 )]
public class SmithyHammer : BaseBashing
{
public override string Damage { get { return WeaponControl.Settings.SmithyHammerDamage; } }
public override int OldStrengthReq { get { return 45; } }
public override int OldMinDamage { get { return 6; } }
public override int OldMaxDamage { get { return 18; } }
public override int OldSpeed { get { return 40; } }
public override int InitMinHits { get { return 31; } }
public override int InitMaxHits { get { return 60; } }
[Constructable]
public SmithyHammer()
: base(0x13E3)
{
Weight = 8.0;
Layer = Layer.OneHanded;
Name = "Smith Hammer";
}
public SmithyHammer(Serial serial)
: base(serial)
{ }
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
var version = reader.ReadInt();
}
}
}
And in the second use I have it as a tool
namespace Server.Items
{
[FlipableAttribute( 0x13E3, 0x13E4 )]
public class SmithHammer : BaseTool
{
public override CraftSystem CraftSystem{ get{ return DefBlacksmithy.CraftSystem; } }
[Constructable]
public SmithHammer() : base( 0x13E3 )
{
Weight = 8.0;
Layer = Layer.OneHanded;
}
[Constructable]
public SmithHammer( int uses ) : base( uses, 0x13E3 )
{
Weight = 8.0;
Layer = Layer.OneHanded;
}
public SmithHammer( Serial serial ) : base( serial )
{
}
public override void Serialize( GenericWriter writer )
{
base.Serialize( writer );
writer.Write( (int) 0 ); // version
}
public override void Deserialize( GenericReader reader )
{
base.Deserialize( reader );
int version = reader.ReadInt();
}
}
}
Is it not possible to make this item do both functions?
There is a mechanism for such scenarios - interfaces. Classes in C# does not support multiple inheritance but support implementing multiple interfaces. In this case you can create two interfaces (or even more) representing required contracts (i.e. interfaces):
public interface IBashing
{
string Damage { get; }
int OldStrengthReq { get; }
// ...
// rest of properties/methods for bashing/weapon
}
public interface ITool
{
CraftSystem CraftSystem { get; }
// ...
}
And implement them both the Hammer class:
public class SmithHammer : IBashing, ITool
{
public string Damage { get { return WeaponControl.Settings.SmithyHammerDamage; } }
public int OldStrengthReq { get { return 45; } }
public CraftSystem CraftSystem { get{ return DefBlacksmithy.CraftSystem; } }
// rest of implemetations
}
And clients can use this hammer class instance via interface or using type testing. For example if you introduce IItem interface to store everything in the inventory (i.e interface IBashing : IItem and interface ITool : IItem) it can look like this:
var inventory = new List<IItem>();
// add some items
// pick some i'th item:
var item = inventory[i];
var tool = item as ITool; // or use pattern matching here
if(tool != null)
{
// use tool
}
else
{
....
}
Sharing implementation is not that easy with interfaces (unless you can and want to use default interface implementations) but can be achieved via composition and wrapping, i.e.:
public class SmithyHammerBashing : BaseBashing
{
public override string Damage { get { return WeaponControl.Settings.SmithyHammerDamage; } }
public override int OldStrengthReq { get { return 45; } }
}
public class SmithHammer : IBashing, ITool
{
private readonly SmithyHammerBashing Bashing = new SmithyHammerBashing(); // or construct some other way
public string Damage { get { return Bashing.Damage; } }
public int OldStrengthReq { get { return Bashing.OldStrengthReq; } }
// the same approach for ITool
}
Related
I try to simulate the decorator pattern in C#.
So I have these classes:
public abstract class Car
{
// private string description;
public abstract string Descripton
{
get;
}
public abstract int Cost();
}
public abstract class CarDecorator : Car
{
protected Car _decorated;
//private string description;
public CarDecorator(Car decoratied)
{
this._decorated = decoratied;
}
public override string Descripton
{
get
{
return _decorated.Descripton;
}
}
public override int Cost()
{
return _decorated.Cost();
}
public class EnhancedAutoPilot : CarDecorator
{
public EnhancedAutoPilot(Car car):base(car)
{
this._decorated = car;
}
public override string Descripton
{
get
{
return _decorated.Descripton + ", Enhanced autopilot";
}
}
public override int Cost()
{
return _decorated.Cost() + 5000;
}
}
public class ModelXS:Car
{
protected Car _decorated;
public string Description = "Model XS";
public override string Descripton
{
get
{
return _decorated.Descripton;
}
}
public override int Cost()
{
return 5500;
}
}
public class ModelXXX : Car
{
protected Car _decorated;
public string Description = "ModelXXX";
public override string Descripton
{
get
{
return _decorated.Descripton;
}
}
public override int Cost()
{
return 73000;
}
}
public class RearFacingSeats:CarDecorator
{
public RearFacingSeats(Car car):base(car)
{
this._decorated = car;
}
public override string Descripton
{
get
{
return _decorated.Descripton + ", Rear Facing Seats ";
}
}
public override int Cost()
{
return _decorated.Cost() + 4000;
}
}
public class SmartAirSuspension: CarDecorator
{
public SmartAirSuspension(Car car):base(car)
{
this._decorated = car;
}
public override string Descripton
{
get
{
return _decorated.Descripton + ", Smart Air Suspension ";
}
}
public override int Cost()
{
return _decorated.Cost() + 2500;
}
}
class Program
{
static void Main(string[] args)
{
Car car = new RearFacingSeats(new SmartAirSuspension(new EnhancedAutoPilot()));
}
}
But then I get this error:
There is no argument given that corresponds to the required formal parameter 'car' of 'EnhancedAutoPilot.EnhancedAutoPilot(Car)'
Your Cars are wrong, they look like decorators but are not, in fact they are supposed to be just implementations of Cars. Like this one:
public class ModelXS : Car
{
public override string Descripton
{
get
{
return "Model XS";
}
}
public override int Cost()
{
return 5500;
}
}
After that you can call the constructors like in #Richard 's answer and you are golden.
and you can ditch
public EnhancedAutoPilot(Car car):base(car)
{
this._decorated = car; // <<-- this lines
}
because you do that assignment in the base constructor of the CarDecorator class already.
You're using new EnhancedAutoPilot() constructor without parameters and it requires a Car parameter in your contructor signature.
public EnhancedAutoPilot(Car car):base(car)
Another issue i see is that you have _decorated in your Car class. The decorated object should only be in the Decorator classes.
So i would modify your car classes this way :
public class ModelXXX : Car
{
public override string Descripton => "ModelXXX";
public override int Cost()
{
return 73000;
}
}
public class ModelXS : Car
{
public override string Descripton => "Model XS";
public override int Cost()
{
return 5500;
}
}
And main would look like this :
static void Main(string[] args)
{
Car car = new ModelXXX();
car = new EnhancedAutoPilot(car);
car = new SmartAirSuspension(car);
car = new RearFacingSeats(car);
Console.Writeline(car.Descripton);
}
The error is telling you that you are not passing a value to the EnhancedAutoPilot() contstructor. All of your decorators require a Car instance be passed, thus you must instantiate a car first, before calling your decorators.
It looks like ModelXS and ModelXXX are types of cars, so the Program class should be:
class Program
{
static void Main(string[] args)
{
Car decoratedCar =
new RearFacingSeats(
new SmartAirSuspension(
new EnhancedAutoPilot(
new ModelXS())));
}
}
I have X classes with different information and calculation methods that should be shared but could be overwritten, so:
class Rule1 {
int type = 1;
string name = "Rule";
public float Calc()
{
return 1 + 2 + type; // SAME
}
}
class Rule2 {
int type = 2;
string name = "Rule2";
public float Calc()
{
return 1 + 2 + type; // SAME
}
}
class Rule3 {
int type = 3;
string name = "Rule3";
public float Calc()
{
return 3 + 4 + type; // DIFFERENT
}
}
What I want to write in the calling methods are like this:
class Calculator
{
public void Do(List<IRules> ruleList)
{
foreach(var rule in ruleList)
{
rule.Calc();
}
}
}
So how would my interface should have to look like and how to abstract the calc method as default implementation but overwriteable?
If you have an implementation that's correct for most inheritors but not all, mark it virtual and override it in a derived class:
public class BaseCalculation
{
public virtual float Calculate()
{
return 42;
}
}
public class HalfCalculation : BaseCalculation
{
public override float Calculate()
{
return 21;
}
}
You can now use the base class, BaseCalculation, instead of an interface. If you insist on still using an interface, then you can still define the Calculate() method in an interface and apply that to your base class:
public interface IRules
{
float Calculate();
}
public class BaseCalculation : IRules
{
// same as above
With the added benefit that you can apply this interface to other classes that also calculate something, but without any of the logic that's in BaseCalculation.
You can try this using an asbtract base class and polymorphism on Calc.
What is polymorphism
No need to use interface unless you have a real and good reason to do that.
What is the difference between an interface and a class
We use a protected constructor to propagate the parameters.
class Calculator
{
public void Do(List<RuleBase> ruleList)
{
foreach ( var rule in ruleList )
{
// do what you want with the result of rule.Calc();
}
}
}
public abstract class RuleBase
{
public int Type { get; private set; }
public string Name { get; private set; }
public abstract float Calc();
protected RuleBase(int type, string name)
{
Type = type;
Name = name;
}
}
public class Rule1 : RuleBase
{
public override float Calc()
{
return 1 + 2 + Type;
}
public Rule1()
: base(1, "Rule1")
{
}
protected Rule1(int type, string name)
: base(type, name)
{
}
}
public class Rule2 : Rule1
{
public Rule2()
: base(2, "Rule2")
{
}
protected Rule2(int type, string name)
: base(type, name)
{
}
}
public class Rule3 : RuleBase
{
public override float Calc()
{
return 3 + 4 + Type;
}
public Rule3()
: base(3, "Rule3")
{
}
protected Rule3(int type, string name)
: base(type, name)
{
}
}
If you want an interface create it and add it to RuleBase:
public interface IRule
{
float Calc();
}
public abstract class RuleBase : IRule
You are searching for inherited class and virtual method (wich allows override) :
class GenericRule {
int type = 1;
string name = "Rule";
public virtual float Calc()
{
return 1 + 2 + type; // SAME
}
}
class Rule3 : GenericRule
{
int type = 3;
string name = "Rule3";
public override float Calc()
{
return 3 + 4 + type; // DIFFERENT
}
}
class Calculator
{
public void Do(List<GenericRule> ruleList)
{
foreach(var rule in ruleList)
{
rule.Calc();
}
}
}
Every class must support the interface. The implementation of method Calc in each class is not important. They can be the same or different.
If you want to have a standard implementation (virtual implementation), you could use a base class and overwrite the method in some classes (in your example Rule3).
If you do not want a standard implmentation (virtual implementation), you could use an abstract base class and overwrite the method in all classes (in your example Rule1, Rule2 and Rule3).
But that has nothing to do with the interface you want to use.
Complete working example (just using the interface):
using System;
using System.Collections.Generic;
namespace Temp
{
class Program
{
static void Main(string[] args)
{
var calc = new Calculator();
var rules = new List<IRule>() { new Rule1(), new Rule2(), new Rule3() };
calc.Do(rules);
Console.WriteLine(calc.GetTotal());
Console.ReadKey();
}
}
public interface IRule
{
float Calc();
}
public class Rule1 : IRule
{
int type = 1;
string name = "Rule";
public float Calc()
{
return 1 + 2 + type; // SAME
}
}
public class Rule2 : IRule
{
int type = 2;
string name = "Rule2";
public float Calc()
{
return 1 + 2 + type; // SAME
}
}
public class Rule3 : IRule
{
int type = 3;
string name = "Rule3";
public float Calc()
{
return 3 + 4 + type; // DIFFERENT
}
}
public class Calculator
{
private float _total = 0;
public void Do(List<IRule> ruleList)
{
foreach (var rule in ruleList)
{
_total += rule.Calc();
}
}
public float GetTotal()
{
return _total;
}
}
}
I have a abstract Class figures which contains Abstract properties
and I am Overriding them in Derived class Rectangle and
Square. Now, iI want to implement this with Interface. But I can't use
constructor and neither I can't Declare the Variable inside the
Interface. So, how to implement this using Interface where Figures Should be Interface and Square and Rectangle should be class?
abstract class Figures
{
int Width;
int _cs;
public Figures(int Width)
{
CS = Width;
}
public abstract int getarea
{
get;
}
public abstract int getperm
{
get;
}
public abstract int CS
{
set;
}
public abstract void display();
}
class Square : Figures
{
int _CsS;
public Square(int c) : base(c)
{
}
public override int getarea
{
get
{
return (_CsS * _CsS);
}
}
public override int getperm
{
get
{
return (2 * _CsS * _CsS);
}
}
public override int CS
{
set
{
_CsS = value;
}
}
public override void display()
{
Console.WriteLine("area={0} and perimeter={1}", getarea, getperm);
}
}
class Rectangle : Figures
{
int H;
int _csr;
public Rectangle(int H, int W) : base(W)
{
this.H = H;
}
public override int getarea
{
get
{
return H * _csr;
}
}
public override int getperm
{
get
{
return 2 * H * _csr;
}
}
public override int CS
{
set
{
_csr = value;
}
}
public override void display()
{
Console.WriteLine("area={0} and perimeter={1}", getarea, getperm);
}
}
so how to implement this using Interface
By definition, an interface won't let you implement anything. You can only specify things.
So you will have to remove the ctor and the fields from the interface IFigures and re-implement them in every class. You could reuse an implementation with a abstract class FiguresBase: IFigures but that's not always the best design.
It all depends on why you want the interface and how you will use it.
You can do something like this:
interface IFigures
{
int getarea
{
get;
}
int getperm
{
get;
}
int CS
{
set;
}
void display();
}
Thenk you can implement this interface from your classes and do your logic inside the class itself. So instead of putting the properties logic inside of your abstract class you will have to write them in your child classes.
class Square : IFigures
{
int _CsS;
public Square(int c)
{
CS = c;
}
public int getarea
{
get
{
return (_CsS * _CsS);
}
}
public int getperm
{
get
{
return (2 * _CsS * _CsS);
}
}
public int CS
{
set
{
_CsS = value;
}
}
public void display()
{
Console.WriteLine("area={0} and perimeter={1}", getarea, getperm);
}
//here you have implemented properties
}
Your abstract class is a good thing. It lets you re-use code.
Interfaces (i.e. contracts) are also good if you want to achieve a loosely coupled system.
You can use abstract classes and interfaces together, to achieve both code reusability and loosely coupled parts.
public interface IFigures
{
int getarea();
}
public abstract class Figures : IFigures
{
public abstract int getarea();
//opportunity for code reuse
protected int getarea_internal()
{
throw new NotimplementedExcpetion();
}
}
public class Square : Figures
public class Rectangle: Figures
here is the answer
with class Diagram
Class Diagram of the Program
interface IFigures
{
int Getarea
{
get;
}
int GetPerm
{
get;
}
int CS
{
//get;
set;
}
}
abstract class Figures:IFigures
{
int _Cs;
public Figures( int _Cs)
{
CS = _Cs;
}
public abstract int Getarea
{
get;
}
public abstract int GetPerm
{
get;
}
public abstract int CS
{
//get;
set;
}
public abstract void display();
}
class Circle:Figures
{
int _r, _csc;
public Circle(int _r):base(_r)
{
CS = _r;
}
public override int Getarea
{
get
{
return (_r * _r);
}
}
public override int GetPerm
{
get
{
return (2* _csc * _csc);
}
}
public override void display()
{
Console.WriteLine("area of Circle={0}", (_r * _r));
Console.WriteLine("perimeter of rectangle={0}", (2 * _r * _r));
}
public override int CS
{
//get
//{
// return _csc;
//}
set
{
_csc = value;
}
}
}
class Rectangle:Figures
{
int _L, _csr;
public Rectangle(int _L,int _W):base(_W)
{
this._L = _L;
CS = _W;
}
public override int Getarea
{
get
{
return _csr * _L;
}
}
public override int GetPerm
{
get
{
return (2* _csr * _L);
}
}
public override void display()
{
Console.WriteLine("area of rectangle={0}", (_csr * _L));
Console.WriteLine("perimeter of rectangle={0}", (2* _csr * _L));
}
public override int CS
{
//get
//{
// return _csr;
//}
set
{
_csr = value;
}
}
}
class Program
{
static void Main(string[] args)
{
Figures f = new Rectangle(3, 4);
f.display();
//f.CS = 5;
f.display();
Console.ReadKey();
}
}
For our project, we would like to use ViewModels.
So we decided to create ViewModels for every object we can have :
So the ViewModel looks like this (GroupVM) :
public class GroupVM : EORTCViewModel<Prisma.BO.Group>
{
public GroupVM(Prisma.BO.Group group) : base(group) { }
public string Name
{
get
{
return this._Model.Name;
}
}
public string ShortName
{
get
{
return this._Model.ShortName;
}
}
public int Id
{
get
{
return this._Model.Id;
}
}
[ScriptIgnore]
public ICollection<StudyGroupVM> StudyGroups
{
get
{
return Prisma.Web.Models.Factories.ViewModelFactory<Prisma.BO.StudyGroup>.ToViewModel<StudyGroupVM>(this._Model.StudyGroups);
}
}
}
The StudyVM :
public class StudyVM : EORTCViewModel<Prisma.BO.Study>
{
public StudyVM(Prisma.BO.Study study) : base(study) { }
public string Number
{
get
{
return this._Model.Number;
}
}
[ScriptIgnore]
public ICollection<StudyGroupVM> StudyGroups
{
get
{
return Prisma.Web.Models.Factories.ViewModelFactory<Prisma.BO.StudyGroup>.ToViewModel<StudyGroupVM>(this._Model.StudyGroups);
}
}
}
and the intermediate object (StudyGroup) :
public class StudyGroupVM : EORTCViewModel<Prisma.BO.StudyGroup>
{
public StudyGroupVM(Prisma.BO.StudyGroup studyGroup) : base(studyGroup) { }
public StudyVM Study
{
get
{
return Prisma.Web.Models.Factories.ViewModelFactory<Prisma.BO.Study>.ToViewModel<StudyVM>(this._Model.Study);
}
}
public GroupVM Group
{
get
{
return Prisma.Web.Models.Factories.ViewModelFactory<Prisma.BO.Group>.ToViewModel<GroupVM>(this._Model.Group);
}
}
}
We would like to use a factory that would create ViewModels for every navigation properties.
So we wrote a generic ViewModel factory as follow :
public static class ViewModelFactory<T> where T : IEORTCObject
{
public static R ToViewModel<R>(T model) where R : EORTCViewModel<T>
{
return (R)Activator.CreateInstance(typeof(R), new object[] { model });
}
public static ICollection<R> ToViewModel<R>(ICollection<T> models) where R : EORTCViewModel<T>
{
ICollection<R> viewModels = new List<R>();
foreach (T model in models)
{
viewModels.Add((R)Activator.CreateInstance(typeof(R), new object[] { model }));
}
return viewModels;
}
}
The problem is that when we try to access the StudyGroups property from one of the end object of the relation, it creates correctly the object but then want to recreate the same object because it seems it tries to access the getter for the other end of the relation.
This cause a StackOverFlowException since it never stops (cycles).
Does any of you have any idea how I can solve this issue ?
Can you use memoization to cache your viemodel after it has been created once?
Something like:
public GroupVM Group
{
get
{
if(groupVM == null)
{
groupVM = Prisma.Web.Models.Factories.ViewModelFactory<Prisma.BO.Group>.ToViewModel<GroupVM>(this._Model.Group);
}
return groupVM;
}
}
I have the following C# code. Here the validations are kept outside the class to satisfy Open – Closed Principle. This is working fine. But the challenge is – the validations are not generic. It is specific to employee class (E.g DateOfBirthRuleForEmployee). How do I make the validations generic for all objects (DateOfBirthRuleForAnyObject).
Note: Make Generic <==> Make Type-Independent
Note: I have NameLengthRuleForEmployee validation also. New validation may come in future.
EDIT
Generic Method Example: Using “OfType” in LINQ
CODE
class Program
{
static void Main(string[] args)
{
Employee employee = new Employee();
employee.DateOfBirth = DateTime.Now;
employee.Name = "Lijo";
DateOfBirthRuleForEmployee dobRule = new
DateOfBirthRuleForEmployee();
NameLengthRuleForEmployee nameRule = new
NameLengthRuleForEmployee();
EmployeeManager employeeManager = new EmployeeManager();
employeeManager.AddRules(dobRule);
employeeManager.AddRules(nameRule);
bool result = employeeManager.validateEntity(employee);
Console.WriteLine(result);
Console.ReadLine();
}
}
public interface IEntity
{
}
public interface IRule<TEntity>
{
bool IsValid(TEntity entity);
}
public class DateOfBirthRuleForEmployee : IRule<Employee>
{
public bool IsValid(Employee entity)
{
return (entity.DateOfBirth.Year <= 1975);
}
}
public class NameLengthRuleForEmployee : IRule<Employee>
{
public bool IsValid(Employee employee)
{
return (employee.Name.Length < 5);
}
}
public class Employee : IEntity
{
private DateTime dateOfBirth;
private string name;
public DateTime DateOfBirth
{
get
{
return dateOfBirth;
}
set
{
dateOfBirth = value;
}
}
public string Name
{
get
{
return name;
}
set
{
name = value;
}
}
}
public class EmployeeManager
{
RulesEngine<Employee> engine = new RulesEngine<Employee>();
public void AddRules(IRule<Employee> rule)
{
engine.AddRules(rule);
//engine.AddRules(new NameLengthRuleForEmployee());
}
public bool validateEntity(Employee employee)
{
List<IRule<Employee>> rulesList = engine.GetRulesList();
//No need for type checking. Overcame Invariance problem
bool status = true;
foreach (IRule<Employee> theRule in rulesList)
{
if (!theRule.IsValid(employee))
{
status = false;
break;
}
}
return status;
}
}
public class RulesEngine<TEntity> where TEntity : IEntity
{
private List<IRule<TEntity>> ruleList = new
List<IRule<TEntity>>();
public void AddRules(IRule<TEntity> rule)
{
//invariance is the key term
ruleList.Add(rule);
}
public List<IRule<TEntity>> GetRulesList()
{
return ruleList;
}
}
The challange is for your rules to know which property of what type to validate. You can either provide this by implementing an interface that provides just that as suggested by SLaks or by quessing it dynamically or by providing a concrete rule class with a bit more information on how to access the given property, e.g.:
class NameRule<T> : IRule<T>
{
private Func<T, string> _nameAccessor;
public NameRule(Func<T, string> nameAccessor)
{
_nameAccessor = nameAccessor;
}
public bool IsValid(T instance)
{
return _nameAccessor(instance).Length > 10;
}
}
this ofcourse can be used in the following way:
NameRule<Employee> employeeNameRule = new NameRule<Employee>(x => x.name);
employeeManager.addRule(employeeNameRule);