Background
I have code that receives some deserialized data of type IProduct but the implementing class is unknown at runtime. I'm supposed to pass this data to an overloaded method that accepts an instance of the implementing class.
This can be achieved by using a switch statement, but it will look clunky and would require alot of code. I've solved this by using late-binding and runtime compilation for single entities but I'm unable to figure out how to do this for collections.
Solving the problem for single entities
If I have an object of type IProduct and want to pass this to the correct overloaded method that accepts an implementing class like Toy, Food, Car or something else. How do I achieve this without creating a big switch statement?
Given the following methods and interface:
public interface IProduct
{
string Name { get;}
double Price { get;}
}
public void Store(Apple apple);
public void Store(Toy toy);
public void Store(Car car);
With the switch statement it would look something like this:
IProduct product = new Apple();
switch (product)
{
case Apple apple:
Store(apple);
break;
case Toy toy:
Store(toy);
break;
case Car car:
Store(car);
break;
}
I've managed to reduce this to the following using late-binding and runtime compilation.
IProduct product = new Apple();
Store((dynamic)product);
Question
However, I've not been able to figure out how to do late-binding in a similar fashion when it comes to collections.
Given the following methods:
public static void Store(ICollection<Apple> apples);
public static void Store(ICollection<Toy> toys);
public static void Store(ICollection<Car> cars);
How do I pass this:
ICollection<IProduct> products = new List<IProduct>() { new Apple()};
Is there a way to achieve the same thing without using alot of magical code?
I'm not sure where these Store methods of yours are located. but something like this implementation is what seemed to me as the correct way to do things:
public interface IProduct
{
string Name { get;}
double Price { get;}
void Store(IProduct product);
}
public class Apple : IProduct
{
public Apple(string name, double price)
{
Name = name;
Price = price;
}
public string Name { get; }
public double Price { get; }
public void Store(IProduct product)
{
throw new NotImplementedException();
}
}
public class Toy : IProduct
{
public Toy(string name, double price)
{
Name = name;
Price = price;
}
public string Name { get; }
public double Price { get; }
public void Store(IProduct product)
{
throw new NotImplementedException();
}
}
public class Playground
{
void Test()
{
IProduct apple = new Apple("apple", 11);
ICollection<IProduct> apples = new List<IProduct>() { new Apple("apple", 230)};
apple.Store(apple);
IProduct toy = new Toy("toy", 11);
ICollection<IProduct> toys = new List<IProduct>() { new Toy("toy", 230)};
}
}
Related
In company I work for I am forced to use badly designed models from the third party API I have no access to like:
class Player
{
object Id;
object Name;
}
Each time I use these properties I have to cast them to specific type.
var name = player.Name.ToString();
var id = (int)player.Id;
And I have to lookup the database what the type is.
I was thinking to create exactly the same classes and using something like AutoMapper to map it to my own type each time and create some proxies/wrapper classes over the original ones.
Any solution?
There are two ways I would do this. Either using an extension method or by simply creating your new class with a static Convert method that take the badly designed class as a parameter.
Example 1:
namespace ExcellentDesignedClasses
{
public class NewPlayerClass
{
public NewPlayerClass(int id, string name)
{
Id = id;
Name = name;
}
public static NewPlayerClass Convert(Player player)
{
return new NewPlayerClass((int)player.Id, (string)player.Name);
}
public int Id { get; set; }
public string Name { get; set; }
}
}
Example 2: using Extension Methods
namespace ExcellentDesignedClasses
{
public class NewPlayerClass
{
public NewPlayerClass(int id, string name)
{
Id = id;
Name = name;
}
public int Id { get; set; }
public string Name { get; set; }
}
}
namespace ExcellentDesignedClasses.Extensions
{
public static class Extensions
{
public static NewPlayerClass ConvertToNew(this Player player)
{
return new NewPlayerClass((int)player.Id, (string)player.Name);
}
}
}
namespace MyProgram
{
using ExcellentDesignedClasses.Extensions;
public class Main
{
public void DoSomething()
{
var oldClassStructure = new Player();
var newClassStructure = oldClassStructure.ConvertToNew();
}
}
}
One thing you could do is create an extension method for the properties you care about. The nice thing is it's less work up front: just create an extension method when you find yourself needing to do a cast. You don't have to write any full classes or mapping code. The downside is you have to call a method every time you need a strongly typed property.
For example:
namespace ExtensionMethods
{
public static class MyExtensions
{
public static string GetName(this Player p)
{
return p.Name?.ToString();
}
public static int GetId(this Player p)
{
return Convert.ToInt32(p.Id);
}
}
}
Then your code would look like:
string name = player.GetName();
int id = player.GetId();
I've worked for companies like this. They're the kind that still ask you in the interview if you know .Net, and you find out they mean version 1.1 on an old instance of Server 2003 they need maintained. They're the burnt raisins in the Raisin Bran.
Use inheritance to redefine the craptastic models. That's how I usually fix it. Then, I return what I want from my objects and stop using the classes I based them on.
ex:
class Player
{
public object Id;
public object Name;
}
class UserPlayer : Player
{
public new int Id
{
get
{
return Convert.ToInt32(base.Id);
}
set
{
base.Id = value;
}
}
public new string Name
{
get
{
return base.Name.ToString();
}
set
{
base.Name = value;
}
}
}
A runner up idea for when doing the above will get you in trouble because the person who wrote the code still works for the company and has friends or is, worse, your boss: use a static class to process what you want.
public static class ProcessPlayers
{
public static int ID(Player p)
{
return Convert.ToInt32(p.Id);
}
public static string Name(Player p)
{
return p.Name.ToString();
}
}
You can also just make new objects that each wrap around Player by having a Player as a property, but inheriting the object and overriding its properties is likely the better choice.
we have an interface with a Generic Customer (gold/silver), now lets say i stored the last created cutomer somewhere (Cache/DB/etc).
how do i create a GetCustomer method that returns the type of customer.
Should i add GetCustomer to the base class or interface or elsewhere ? and how do we use GetCustomer ?
Hope that makes sense.
interface ICstomerInterface<T>
{
T MakeCustomer();
}
public abstract class BaseCustomer<T>: ICstomerInterface<T>
{
public string Type { get; set; }
public string Name { get; set; }
// methods
public abstract T MakeCustomer();
}
public class Gold : BaseCustomer<Gold>
{
public override Gold MakeCustomer()
{
var customer = new Gold
{
Type= "Gold",
Name = "Jack"
};
return customer;
}
}
public class Silver : BaseCustomer<Silver>
{
public override Silver MakeCustomer()
{
var customer = new Silver();
customer.Name = "Jones";
customer.Type = "Silver";
return customer;
}
}
The problem with you design is that MakeCustomer is an instance method of the customers. This means, that you must create a customer to be able to call MakeCustomer. In other words, this design will not work!
You have two options: Either simply initialize the customers in their respective constructors, or create a customer factory. This must be a separate class (static or not).
The generic type parameter is superfluous.
public abstract class CustomerBase
{
public CustomerBase(string name)
{
Name = name;
}
public abstract string Type { get; }
public string Name { get; }
}
public class GoldCustomer : CustomerBase
{
public GoldCustomer(string name)
: base(name)
{
}
public override string Type => "Gold";
}
public class SilverCustomer : CustomerBase
{
public SilverCustomer(string name)
: base(name)
{
}
public override string Type => "Silver";
}
The Type property can be a getter only property. It can be abstract in the base class to force concrete customer classes to implement it.
The name must be passed to the constructor to be able to assign different names to different customers.
See also Abstract factory pattern on Wikipedia.
Example:
var customers = new List<CustomerBase> {
new GoldCustomer("Frank"),
new SilverCustomer("Jack")
};
foreach (CustomerBase c in customers) {
Console.WriteLine($"{c.Name} is {c.Type}");
}
Prints:
Frank is Gold
Jack is Silver
See working example: https://dotnetfiddle.net/BiAskT
You could have an extension method to get the customer type (on a static class):
public static Type GetCustomerType<T>(this ICstomerInterface<T> _customer)
{
return typeof(T);
}
All with the intention that you don't have to make redundant code each time you create a new Customer class that implements that interface.
Your sample code doesn't contain a base type that can contain all your customers, i.e. there is no strongly-typed variable that could hold either a BaseCustomer<Gold> or a BaseCustomer<Silver>. There is no type compatibility between those two at all, no more than a Dictionary<int> can be stored as a Dictionary<string> (in fact, even worse, because there isn't covariance in your object model). Given that fact, your question makes little sense, because you'll always have to declare the type parameter to store a customer somewhere, therefore there is no need to learn the type at run time.
But let's say you want a cache that works for both. You'd introduce a non-generic base interface:
public interface ICustomer
{
Guid CustomerGuid { get; }
}
public abstract class BaseCustomer<T>: ICstomerInterface<T>, ICustomer
{
///etc....
Now you can define a cache that could hold all customers:
var cache = new Dictionary<Guid,ICustomer>();
var gold = new Gold();
cache.Add( gold.CustomerGuid, gold );
var silver = new Silver();
cache.Add( silver.CustomerGuid, silver );
Now you can retrieve any customer by its Guid:
var customer = cache[guid];
And to determine its type, just use
bool isGold = customer is Gold;
bool isSilver = customer is Silver;
Or to get a string that tells you the type:
string type = customer.GetType().Name;
It appears that you are trying to use the classic Factory Method.
Personally for simple classes, like the one you are asking about, I would add a static method on the base class, like so:
public abstract class BaseCustomer<T>: ICstomerInterface<T>
{
public static BaseCustomer<T> GetLastCustomer()
{
// Get from storage, the last customer.
}
}
That way your Create customer method is separate from your get customer method but still accessible from anywhere.
This question already has answers here:
Using Interface variables
(12 answers)
Closed 5 years ago.
I have fair understanding of interface/abstract class/class however just trying to understand something else. Look at below code:
namespace AbstractClassExample
{
class Program
{
static void Main(string[] args)
{
BaseEmployee fullTimeEmployee = new FullTimeEmployee();
BaseEmployee contractEmployee = new ContractEmployee();
}
}
public abstract class BaseEmployee
{
public string EmployeeID { get; set; }
public string EmployeeName { get; set; }
public string EmployeeAddress { get; set; }
public abstract double CalculateSalary(int hoursWorked);
}
public class FullTimeEmployee : BaseEmployee
{
public override double CalculateSalary(int hoursWorked)
{
//do something
}
}
public class ContractEmployee : BaseEmployee
{
public override double CalculateSalary(int hoursWorked)
{
//do something
}
}
}
however I fail to get below lines (1st approach):
BaseEmployee fullTimeEmployee = new FullTimeEmployee();
BaseEmployee contractEmployee = new ContractEmployee();
Why not written this way instead (2nd approach):
FullTimeEmployee fullTimeEmployee = new FullTimeEmployee();
it is completely okay to use 2nd approach it will work coz of relation. How would any developer in the work know if above abstract class is in DLL. Probably, will use 1st approach when you've code with you or sort of documentation. Isn't it?
Similar example would also be valid for interface declaration. like:
interface IPointy {
void MyMethod();
}
class Pencil : IPointy {
void MyMethod() {
}
void MyOtherMethod() {
}
}
IPointy itPt = new Pencil();
Isn't 1st approach making it complex? What's good practice? Any good practice vs bad practice with 1st & 2nd?
Using the first approach enables Polymorphism.
Let's say you have a company class:
class Company {
}
Of course, companies have full-time and contract employees. Let's add them as properties:
public FullTimeEmployee[] EmployeesFullTime { get; set; }
public ContractEmployees[] EmployeesContract { get; set; }
This seems all good.
But, what if your company can now have yet another kind of employee that has a different way of calculating his salary? You have to add another property:
public FullTimeEmployee[] EmployeesFullTime { get; set; }
public ContractEmployee[] EmployeesContract { get; set; }
public AnotherKindOfEmployee[] EmployeesOther { get; set; }
That's no good, is it? Every time you add a new kind of employee, you have to add another property!
That's why you use BaseEmployee, it does not care about what kind of employee it holds, and it can still calculate salary!
public BaseEmployee[] AllEmployees { get; set; }
One of the reasons that you'd assign a FullTimeEmployee to a BaseEmployee is that you can put them together into a collection of FullTimeEmployees' andContractEmployees`:
List<BaseEmployee> allEmployees = new List<BaseEmployee>()
{
new FullTimeEmployee() {...},
new FullTimeEmployee() {...},
new ContractEmployee() {...},
new FullTimeEmployee() {...},
}
This has the disadvantage that you can't use (efficiently) functionality of a FullTimeEmployee that ContractEmployees don't have, but if you don't need this functionality while processing allEmployees, this method is preferable above creating two collections of employees. For instance, you could write one function that would work for both FullTimeEmployees and ContractEmployees:
private void PaySalary(List<BaseEmployee> employees)
{
foreach (var employee in employees)
{
var salary = employee.CalculateSalary()
Pay(salary, ...);
}
}
One of the guidelines when creating an object oriented design is that you should design for change, meaning that your design should be such that you could easily add types to your design, or change internals of your classes.
Suppose you'll need a new type of employees, HiredEmployees. Because you derived them from BaseEmployee, you'll know you can calculate their salary. You don't have to change function PaySalary.
This would also have worked if you'd given your FullTimeEmployee and your ContractEmployee an interface:
interface ISalaryReceiver
{
double CalculateSalary(int hoursWorked);
}
class BaseEmployee
{
public string EmployeeID { get; set; }
...
}
class FullTimeEmployee : BaseEmployee, ISalaryReceiver
{
public override double CalculateSalary(int hoursWorked)
{
...
}
}
class ContractEmployee : BaseEmployee, ISalaryReceiver
{
public double CalculateSalary(int hoursWorked)
{
...
}
}
void PaySalary(List<ISalaryReceiver> employees)
{
...
}
This method would work. It is even ready for change: you can invent any employee as long as it implements ISalaryReceiver.
However!
Suppose your BaseEmploye has a function where it needs to CalculateSalary:
class BaseEmployee
{
...
public void PaySalary()
{
double salary = ... // how to calculate the salary?
}
}
You can't let BaseEmployee implement ISalaryReceiver, because a BaseEmployee doesn't know how to calculate the salary.
When using the abstract method, you can tell BaseEmployee, that every object of BaseEmployee knows how to CalculateSalary:
abstract class BaseEmployee
{
abstract double CalculateSalary(...);
public void PaySalary()
{
double salary = this.CalculateSalary(...);
...
}
}
So if your base class needs functions that are different per derived class, and there is no proper default functionality, then your base class needs an abstract function. It is guaranteed that every derived class has implemented this function, and thus the base class can call it.
Because in such cases it is not meaningful to create objects of the base class (after all, the base class doesn't know how to CalculateSalary), the base class has to be declared abstract with the result that you can't create objects of base class. Only object of derived classes that implement CalculateSalary can be created.
One of the benefits of abstract classes is - you can use abstract type for argument type in the method.
Suppose you have a Report class with method Generate which during report generation need to calculate employee salary
public class Report
{
public SalaryReport Generate(BaseEmployee employee)
{
// ...
var salary = employee.CalculateSalary();
// ...
}
}
You don't want use if..else statement in every method where you need calculate salary.
So in Report class doesn't care how CalculateSalary implemented, it only cares that Employee class have this method.
Can anyone explain why the conversion in the return in the switch statement doesn't compile in .net 4? I've updated the example to be more accurate to my situation. The factory itself isn't generic actually.
Even casting "as BaseProductProcessor" does not work IF I'm passing in a base Product (that's actually a StandardProduct). Now if I explicitly pass a StandardProduct type to the factory, then it's ok - but what I have defined is a Product type in all calling methods anyway :|
How to get around this?
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace testing
{
[TestClass]
public class Test
{
[TestMethod]//fails
public void TestFactoryMethodWithBaseTypePassed()
{
Product product = new testing.StandardProduct();
var pp = new testing.ProductProcessorFactory().Create(product);
Assert.IsNotNull(pp);//fails because T coming into create wasn't the derived type
}
[TestMethod]//passes
public void TestFactoryMethodWithExactType()
{
var pp = new testing.ProductProcessorFactory().Create(new testing.StandardProduct());
Assert.IsNotNull(pp);
}
}
public abstract class BaseProductProcessor<T> where T : Product
{
public T Product { get; set; }
public BaseProductProcessor(T product)
{
Product = product;
}
}
public class StandardProductProcessor : BaseProductProcessor<StandardProduct>
{
public StandardProductProcessor(StandardProduct product)
: base(product)
{
}
}
public class ProductProcessorFactory
{
public ProductProcessorFactory()
{
}
public BaseProductProcessor<T> Create<T>(T product) where T : Product
{
switch (product.ProductType)
{
case ProductType.Standard:
var spp = new StandardProductProcessor(product as StandardProduct);
return spp as BaseProductProcessor<T>;//Nulls if T passed with a Product.. how to explicitly say T is a StandardProduct right here in the factory method so it's centralized?
}
return null;// spp as BaseProductProcessor<T>;
}
}
public class Product
{
public ProductType ProductType { get; set; }
}
public enum ProductType
{
Standard,
Special
}
public class StandardProduct : Product
{
}
}
That's because StandardProductProcessor expects an object of type StandardProduct.
At design time you only know that you have a Product.
While every StandardProduct is a Product, that doesn't go the other way around. Not every Product is a StandardProduct, that's why you need to tell the compiler explicitly that you have a StandardProduct
Well, here you want to achieve covariance of template parameter. It is not possible with base classes, but it IS possible with intefaces. So, I suggest you to replace your abstract class BaseProductProcessor<T> with interface:
public interface IBaseProductProcessor<out T> where T : Product // out marks argument as covariant
{
T Product { get; } // absense of setter is crusial here - otherwise you'll violate type safety
}
StandartProcessor:
public class StandardProductProcessor : IBaseProductProcessor<StandardProduct>
{
public StandardProductProcessor(StandardProduct product)
{
Product = product;
}
public StandardProduct Product { get; private set; }
}
and with this, just modify your factory function as following:
public class ProductProcessorFactory
{
public ProductProcessorFactory()
{
}
public IBaseProductProcessor<T> Create<T>(T product) where T : Product
{
switch (product.ProductType)
{
case ProductType.Standard:
var spp = new StandardProductProcessor(product as StandardProduct);
return spp as IBaseProductProcessor<T>;//no more nulls!
}
return null;
}
}
With this modifications, both of your tests will pass.
If you want to learn more about covariance and contravariance(out and in keywords in C#), I recommend the excellent series in Eric Lippert's blog (start with the bottom ones)
I know the feature doesn't exist in C#, but PHP recently added a feature called Traits which I thought was a bit silly at first until I started thinking about it.
Say I have a base class called Client. Client has a single property called Name.
Now I'm developing a re-usable application that will be used by many different customers. All customers agree that a client should have a name, hence it being in the base-class.
Now Customer A comes along and says he also need to track the client's Weight. Customer B doesn't need the Weight, but he wants to track Height. Customer C wants to track both Weight and Height.
With traits, we could make the both the Weight and the Height features traits:
class ClientA extends Client use TClientWeight
class ClientB extends Client use TClientHeight
class ClientC extends Client use TClientWeight, TClientHeight
Now I can meet all my customers' needs without adding any extra fluff to the class. If my customer comes back later and says "Oh, I really like that feature, can I have it too?", I just update the class definition to include the extra trait.
How would you accomplish this in C#?
Interfaces don't work here because I want concrete definitions for the properties and any associated methods, and I don't want to re-implement them for each version of the class.
(By "customer", I mean a literal person who has employed me as a developer, whereas by "client" I'm referring a programming class; each of my customers has clients that they want to record information about)
You can get the syntax by using marker interfaces and extension methods.
Prerequisite: the interfaces need to define the contract which is later used by the extension method. Basically the interface defines the contract for being able to "implement" a trait; ideally the class where you add the interface should already have all members of the interface present so that no additional implementation is required.
public class Client {
public double Weight { get; }
public double Height { get; }
}
public interface TClientWeight {
double Weight { get; }
}
public interface TClientHeight {
double Height { get; }
}
public class ClientA: Client, TClientWeight { }
public class ClientB: Client, TClientHeight { }
public class ClientC: Client, TClientWeight, TClientHeight { }
public static class TClientWeightMethods {
public static bool IsHeavierThan(this TClientWeight client, double weight) {
return client.Weight > weight;
}
// add more methods as you see fit
}
public static class TClientHeightMethods {
public static bool IsTallerThan(this TClientHeight client, double height) {
return client.Height > height;
}
// add more methods as you see fit
}
Use like this:
var ca = new ClientA();
ca.IsHeavierThan(10); // OK
ca.IsTallerThan(10); // compiler error
Edit: The question was raised how additional data could be stored. This can also be addressed by doing some extra coding:
public interface IDynamicObject {
bool TryGetAttribute(string key, out object value);
void SetAttribute(string key, object value);
// void RemoveAttribute(string key)
}
public class DynamicObject: IDynamicObject {
private readonly Dictionary<string, object> data = new Dictionary<string, object>(StringComparer.Ordinal);
bool IDynamicObject.TryGetAttribute(string key, out object value) {
return data.TryGet(key, out value);
}
void IDynamicObject.SetAttribute(string key, object value) {
data[key] = value;
}
}
And then, the trait methods can add and retrieve data if the "trait interface" inherits from IDynamicObject:
public class Client: DynamicObject { /* implementation see above */ }
public interface TClientWeight, IDynamicObject {
double Weight { get; }
}
public class ClientA: Client, TClientWeight { }
public static class TClientWeightMethods {
public static bool HasWeightChanged(this TClientWeight client) {
object oldWeight;
bool result = client.TryGetAttribute("oldWeight", out oldWeight) && client.Weight.Equals(oldWeight);
client.SetAttribute("oldWeight", client.Weight);
return result;
}
// add more methods as you see fit
}
Note: by implementing IDynamicMetaObjectProvider as well the object would even allow to expose the dynamic data through the DLR, making the access to the additional properties transparent when used with the dynamic keyword.
Traits can be implemented in C# 8 by using default interface methods. Java 8 introduced default interface methods for this reason too.
Using C# 8, you can write almost exactly what you proposed in the question. The traits are implemented by the IClientWeight, IClientHeight interfaces that provide a default implementation for their methods. In this case, they just return 0:
public interface IClientWeight
{
int getWeight()=>0;
}
public interface IClientHeight
{
int getHeight()=>0;
}
public class Client
{
public String Name {get;set;}
}
ClientA and ClientB have the traits but don't implement them. ClientC implements only IClientHeight and returns a different number, in this case 16 :
class ClientA : Client, IClientWeight{}
class ClientB : Client, IClientHeight{}
class ClientC : Client, IClientWeight, IClientHeight
{
public int getHeight()=>16;
}
When getHeight() is called in ClientB through the interface, the default implementation is called. getHeight() can only be called through the interface.
ClientC implements the IClientHeight interface so its own method is called. The method is available through the class itself.
public class C {
public void M() {
//Accessed through the interface
IClientHeight clientB = new ClientB();
clientB.getHeight();
//Accessed directly or through the class
var clientC = new ClientC();
clientC.getHeight();
}
}
This SharpLab.io example shows the code produced from this example
Many of the traits features described in the PHP overview on traits can be implemented easily with default interface methods. Traits (interfaces) can be combined. It's also possible to define abstract methods to force classes to implement certain requirements.
Let's say we want our traits to have sayHeight() and sayWeight() methods that return a string with the height or weight. They'd need some way to force exhibiting classes (term stolen from the PHP guide) to implement a method that returns the height and weight :
public interface IClientWeight
{
abstract int getWeight();
String sayWeight()=>getWeight().ToString();
}
public interface IClientHeight
{
abstract int getHeight();
String sayHeight()=>getHeight().ToString();
}
//Combines both traits
public interface IClientBoth:IClientHeight,IClientWeight{}
The clients now have to implement thet getHeight() or getWeight() method but don't need to know anything about the say methods.
This offers a cleaner way to decorate
SharpLab.io link for this sample.
C# language (at least to version 5) does not have support for Traits.
However, Scala has Traits and Scala runs on the JVM (and CLR). Therefore, it's not a matter of run-time, but simply that of the language.
Consider that Traits, at least at the Scala sense, can be thought of as "pretty magic to compile in proxy methods" (they do not affect the MRO, which is different from Mixins in Ruby). In C# the way to get this behavior would be to use interfaces and "lots of manual proxy methods" (e.g. composition).
This tedious process could be done with a hypothetical processor (perhaps automatic code generation for a partial class via templates?), but that's not C#.
Happy coding.
I'd like to point to NRoles, an experiment with roles in C#, where roles are similar to traits.
NRoles uses a post-compiler to rewrite the IL and inject the methods into a class. This allows you to write code like that:
public class RSwitchable : Role
{
private bool on = false;
public void TurnOn() { on = true; }
public void TurnOff() { on = false; }
public bool IsOn { get { return on; } }
public bool IsOff { get { return !on; } }
}
public class RTunable : Role
{
public int Channel { get; private set; }
public void Seek(int step) { Channel += step; }
}
public class Radio : Does<RSwitchable>, Does<RTunable> { }
where class Radio implements RSwitchable and RTunable. Behind the scenes, Does<R> is an interface with no members, so basically Radio compiles to an empty class. The post-compilation IL rewriting injects the methods of RSwitchable and RTunable into Radio, which can then be used as if it really derived from the two roles (from another assembly):
var radio = new Radio();
radio.TurnOn();
radio.Seek(42);
To use radio directly before rewriting happened (that is, in the same assembly as where the Radio type is declared), you have to resort to extensions methods As<R>():
radio.As<RSwitchable>().TurnOn();
radio.As<RTunable>().Seek(42);
since the compiler would not allow to call TurnOn or Seek directly on the Radio class.
There is an academic project, developed by Stefan Reichart from the Software Composition Group at the University of Bern (Switzerland), which provides a true implementation of traits to the C# language.
Have a look at the paper (PDF) on CSharpT for the full description of what he has done, based on the mono compiler.
Here is a sample of what can be written:
trait TCircle
{
public int Radius { get; set; }
public int Surface { get { ... } }
}
trait TColor { ... }
class MyCircle
{
uses { TCircle; TColor }
}
Building on what Lucero suggested, I came up with this:
internal class Program
{
private static void Main(string[] args)
{
var a = new ClientA("Adam", 68);
var b = new ClientB("Bob", 1.75);
var c = new ClientC("Cheryl", 54.4, 1.65);
Console.WriteLine("{0} is {1:0.0} lbs.", a.Name, a.WeightPounds());
Console.WriteLine("{0} is {1:0.0} inches tall.", b.Name, b.HeightInches());
Console.WriteLine("{0} is {1:0.0} lbs and {2:0.0} inches.", c.Name, c.WeightPounds(), c.HeightInches());
Console.ReadLine();
}
}
public class Client
{
public string Name { get; set; }
public Client(string name)
{
Name = name;
}
}
public interface IWeight
{
double Weight { get; set; }
}
public interface IHeight
{
double Height { get; set; }
}
public class ClientA : Client, IWeight
{
public double Weight { get; set; }
public ClientA(string name, double weight) : base(name)
{
Weight = weight;
}
}
public class ClientB : Client, IHeight
{
public double Height { get; set; }
public ClientB(string name, double height) : base(name)
{
Height = height;
}
}
public class ClientC : Client, IWeight, IHeight
{
public double Weight { get; set; }
public double Height { get; set; }
public ClientC(string name, double weight, double height) : base(name)
{
Weight = weight;
Height = height;
}
}
public static class ClientExt
{
public static double HeightInches(this IHeight client)
{
return client.Height * 39.3700787;
}
public static double WeightPounds(this IWeight client)
{
return client.Weight * 2.20462262;
}
}
Output:
Adam is 149.9 lbs.
Bob is 68.9 inches tall.
Cheryl is 119.9 lbs and 65.0 inches.
It isn't quite as nice as I'd like, but it's not too bad either.
This is really an suggested extension to Lucero's answer where all the storage was in the base class.
How about using dependency properties for this?
This would have the effect of making the client classes light weight at run time when you have many properties that are not always set by every descendant. This is because the values are stored in a static member.
using System.Windows;
public class Client : DependencyObject
{
public string Name { get; set; }
public Client(string name)
{
Name = name;
}
//add to descendant to use
//public double Weight
//{
// get { return (double)GetValue(WeightProperty); }
// set { SetValue(WeightProperty, value); }
//}
public static readonly DependencyProperty WeightProperty =
DependencyProperty.Register("Weight", typeof(double), typeof(Client), new PropertyMetadata());
//add to descendant to use
//public double Height
//{
// get { return (double)GetValue(HeightProperty); }
// set { SetValue(HeightProperty, value); }
//}
public static readonly DependencyProperty HeightProperty =
DependencyProperty.Register("Height", typeof(double), typeof(Client), new PropertyMetadata());
}
public interface IWeight
{
double Weight { get; set; }
}
public interface IHeight
{
double Height { get; set; }
}
public class ClientA : Client, IWeight
{
public double Weight
{
get { return (double)GetValue(WeightProperty); }
set { SetValue(WeightProperty, value); }
}
public ClientA(string name, double weight)
: base(name)
{
Weight = weight;
}
}
public class ClientB : Client, IHeight
{
public double Height
{
get { return (double)GetValue(HeightProperty); }
set { SetValue(HeightProperty, value); }
}
public ClientB(string name, double height)
: base(name)
{
Height = height;
}
}
public class ClientC : Client, IHeight, IWeight
{
public double Height
{
get { return (double)GetValue(HeightProperty); }
set { SetValue(HeightProperty, value); }
}
public double Weight
{
get { return (double)GetValue(WeightProperty); }
set { SetValue(WeightProperty, value); }
}
public ClientC(string name, double weight, double height)
: base(name)
{
Weight = weight;
Height = height;
}
}
public static class ClientExt
{
public static double HeightInches(this IHeight client)
{
return client.Height * 39.3700787;
}
public static double WeightPounds(this IWeight client)
{
return client.Weight * 2.20462262;
}
}
This sounds like PHP's version of Aspect Oriented Programming. There are tools to help like PostSharp or MS Unity in some cases. If you want to roll-your-own, code-injection using C# Attributes is one approach, or as suggested extension methods for limited cases.
Really depends how complicated you want to get. If you are trying to build something complex I'd be looking at some of these tools to help.