I have these classes:
public interface IPerson
{
string Name { get; set; }
}
public class Person : IPerson
{
public string Name { get; set; }
}
public interface IRoom
{
List<Furniture> Furnitures { get; set; }
List<Person> People { get; set; }
}
public class Room : IRoom
{
public List<Furniture> Furnitures { get; set; }
public List<Person> People { get; set; }
}
public enum Furniture
{
Table,
Chair
}
And I have this extension method:
public static void Assign<T>(this IRoom sender, Func<IRoom,ICollection<T>> property, T value)
{
// How do I actually add a Chair to the List<Furniture>?
}
And I want to use it like this:
var room = new Room();
room.Assign(x => x.Furnitures, Furniture.Chair);
room.Assign(x => x.People, new Person() { Name = "Joe" });
But I have no idea how to add T to ICollection<T>.
Trying to learn generics and delegates. I know room.Furnitures.Add(Furniture.Chair) works better :)
public static void Assign<T>(this IRoom room, Func<IRoom, ICollection<T>> collectionSelector, T itemToAdd)
{
collectionSelector(room).Add(itemToAdd);
}
You don't need a Func<IRoom,ICollection<T>> here. This takes room as argument and returns ICollection<T>. ICollection<T> as a parameter is enough. Let's rewrite your code as following to make it work.
public static void Assign<T>(this IRoom sender, ICollection<T> collection, T value)
{
collection.Add(value);
}
Then call it as
room.Assign(room.Furnitures, Furniture.Chair);
room.Assign(room.People, new Person() { Name = "Joe" });
If you're not satisfied with this approach and you need your own approach only then try the following
public static void Assign<T>(this IRoom sender, Func<IRoom, ICollection<T>> property, T value)
{
property(sender).Add(value);
}
Then call it with your own syntax should work
room.Assign(x => x.Furnitures, Furniture.Chair);
room.Assign(x => x.People, new Person() { Name = "Joe" });
Note:Keep in mind you've not initialized your collections, this will result in NullReferenceException, so to get rid of it add a contructor in your Room class as follows
public Room()
{
Furnitures = new List<Furniture>();
People = new List<Person>();
}
Related
I need a method that returns a keySelector, which can be used when invoking an OrderBy expression. The problem is that a keySelector is a generic delegate and I would like the method to return keySelectors with different data types on TKey:
Func<TSource,TKey> keySelector
I would like to accomplish this, but instead of using lambda expressions a method that returns a keySelector (TKey=string or int):
IEnumerable<Person> orderedByFirstName = persons.OrderBy(p => p.FirstName);
IEnumerable<Person> orderedByAge = persons.OrderBy(p => p.Age);
Is it possible to have a method that returns keySelectors with different types on TKey in some way? It isn't possible to return lambda expressions, but something like that...
As long as the method only returns keySelectors of data type string everything works fine:
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
}
public class Behavior
{
public virtual string GetOrderByKeySelector(Person p)
{
return p.FirstName;
}
}
public class SpecializedBehavior : Behavior
{
public override string GetOrderByKeySelector(Person p)
{
return p.LastName;
}
}
List<Person> persons = new List<Person>
{
new Person{Age=10, FirstName="Pelle", LastName="Larsson"},
new Person{Age=90, FirstName="Nils", LastName="Nilsson"},
new Person{Age=15, FirstName="Olle", LastName="Johansson"},
new Person{Age=30, FirstName="Kalle", LastName="Svensson"}
};
Used like this:
SpecializedBehavior behavior = new SpecializedBehavior();
IEnumerable<Person> orderedResult = persons.OrderBy(behavior.GetOrderByKeySelector);
How about taking in the collection to the method instead.
void Main()
{
SpecializedBehavior behavior = new SpecializedBehavior();
IEnumerable<Person> orderedResult = behavior.Sort(persons);
}
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
}
public class Behavior
{
public virtual IEnumerable<Person> Sort(IEnumerable<Person> persons)
{
return persons.OrderBy(p => p.FirstName);
}
}
public class SpecializedBehavior : Behavior
{
public override IEnumerable<Person> Sort(IEnumerable<Person> persons)
{
return persons.OrderBy(p => p.Age);
}
}
List<Person> persons = new List<Person>
{
new Person{Age=10, FirstName="Pelle", LastName="Larsson"},
new Person{Age=90, FirstName="Nils", LastName="Nilsson"},
new Person{Age=15, FirstName="Olle", LastName="Johansson"},
new Person{Age=30, FirstName="Kalle", LastName="Svensson"}
};
This answer is just to illustrate #LasseVågsætherKarlsen's comment and all the credit should go to him:
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
}
public class PersonByFirstNameComparer : IComparer<Person>
{
public int Compare(Person left, Person right) =>
left.FirstName.CompareTo(right.FirstName);
}
public class Behavior
{
public virtual IComparer<Person> GetComparer() => PersonByFirstNameComparer();
}
public class PersonByLastNameComparer : IComparer<Person>
{
public int Compare(Person left, Person right) =>
left.LastName.CompareTo(right.LastName);
}
public class SpecializedBehavior : Behavior
{
public override IComparer<Person> GetComparer() => new PersonByLastNameComparer();
}
which can be used the following way:
public static void Main()
{
var people = new List<Person>
{
new Person{Age=10, FirstName="Pelle", LastName="Larsson"},
new Person{Age=90, FirstName="Nils", LastName="Nilsson"},
new Person{Age=15, FirstName="Olle", LastName="Johansson"},
new Person{Age=30, FirstName="Kalle", LastName="Svensson"}
};
var standardBehavior = new Behavior();
IEnumerable<Person> orderedPeople1 =
people.OrderBy(p => p, standardBehavior.GetComparer());
foreach (Person p in orderedPeople1)
{
Console.WriteLine($"{p.FirstName} {p.LastName}");
}
var specializedBehavior = new SpecializedBehavior();
IEnumerable<Person> orderedPeople2 =
people.OrderBy(p => p, specializedBehavior.GetComparer());
foreach (Person p in orderedPeople2)
{
Console.WriteLine($"{p.FirstName} {p.LastName}");
}
}
Link to fiddle
I have the following code:
public interface BaseInterface
{
int ID { get; }
}
public interface SpecialInterface1 : BaseInterface
{
int price { get; }
}
public interface SpecialInterface1 : BaseInterface
{
int xyz { get; }
}
public class Implementation1 : SpecialInterface
{
int price { get; }
int ID { get; internal set; }
}
public class Implementation2 : SpecialInterface
{
int xyz { get; }
int ID { get; internal set; }
}
Now in a Management class I want to add the objects that implement BaseInterface into a List.
I know that I can use as or is to cast the interface to an implementation, but in my project, I have about 10 special interfaces with an implementation each so I would have to write a really big if statements.
public void Add(BaseInterface u, int id)
{
if (u is Implementation1)
{
((Implementation1)u).ID = id;
Units.Add(u);
}
if (u is Implementation2)
{
((Implementation2)u).ID = id;
Units.Add(u);
}
}
My goal is that the id is not changeable outside the implementation and I would provide only the interfaces outside my dll so none can change the id.
A solution would be to add an extra interface. This eliminates the internal setter in your implementation.
internal interface IChangeID
{
void SetID(int id);
}
public interface IBaseInterface
{
int ID { get; }
}
public class Implementation : IBaseInterface,
IChangeID
{
public void SetID(int id) { ID = id; }
public int ID { get; private set; }
}
Only the real implementations should implement IChangeID. Returning IBaseInterface or ISpecialInterface will hide the setter, because those interfaces do not inherit from IChangeID.
This would change your add into:
public void Add(BaseInterface u, int id)
{
((IChangeID)u).SetID(id);
Units.Add(u);
}
If you do want to return the concrete types, not interfaces. You could implement the given interface explicit. This will hide the set method even from the concrete implementation.
public class Implementation : IBaseInterface,
IChangeID
{
void IChangeID.SetID(int id) { ID = id; }
public int ID { get; private set; }
}
var obj = new Implementation();
obj.SetID() // This WILL NOT Compile
If you don't want to modify the interfaces and implementations, you could use C# 7's pattern matching to access the implementation type without casting. It requires 3 lines per implementation type but avoids modifying the classes:
public void Add(BaseInterface u, int id)
{
switch(u)
{
case Implementation1 u1:
u1.ID = id;
break;
case Implementation2 u1:
u1.ID = id;
break;
default :
throw new ArgumentException("Unexpected implementation!");
}
Units.Add(u);
}
The obvious disadvantage is that the code will have to be modified if a new implementation is added.
Another option is to use dynamic, losing type safety. This will fail at runtime if some implementation doesn't have a setter (eg because it was replaced by constructor initialization)
public void Add(BaseInterface u, int id)
{
dynamic x =u;
x.ID=id;
Units.Add(x);
}
While I like this answer the best,
I recommend making the ID a required parameter of all the implementation's constructors, and then to use a factory pattern to generate any instance you require. This makes any instance without the ID set throw an exception at compile time rather than runtime reducing the probability of exceptions.
Here is a simple example that gets you what you want without an additional interface. Should you choose you can combine my answer with #Iqon's answer.
public interface IInterface
{
int ID { get; }
}
internal class InternalImplementation: IInterface {
public InternalImplementation(int ID) { this.ID = ID; }
public int ID { get; set; }
}
public class MyImplementationFactoryService {
public IInterface Create() {
int id = 1 // Or however you get your ID, possibly from a DB query?
return new InternalImplementation(id);
}
public IInterface Create(type|enum createtype) {
// return type based on typeof or enum
}
}
In case you want to use reflection to set property, code below may help
public interface IBaseInterface
{
int ID { get; }
}
public class Impl1 : IBaseInterface
{
public int ID { get; internal set; }
public int Price {get; set;}
}
public class Impl2 : IBaseInterface
{
public int ID { get { return 0;} }
public int Subscription {get; set;}
}
public class Program
{
public static void Main(string[] args)
{
IBaseInterface obj1 = new Impl1();
SetProperty(obj1, "ID", 100);
Console.WriteLine("Object1 Id is {0}", obj1.ID);
IBaseInterface obj2 = new Impl2();
SetProperty(obj2, "ID", 500);
Console.WriteLine("Object2 Id is {0}", obj2.ID);
}
private static void SetProperty(IBaseInterface obj, string propertyName, object id){
if(obj.GetType().GetProperty(propertyName).CanWrite) {
obj.GetType().GetProperty(propertyName).SetValue(obj, id);
Console.WriteLine("CanWrite property '{0}' : {1}" , propertyName, obj.GetType().GetProperty(propertyName).CanWrite);
}
}
}
Output
CanWrite property 'ID' : True
Object1 Id is 100
Object2 Id is 0
I am stuck on interfaces and inheritance. If I implement two classes who both have an interface each, how would I be able to add the properties of Class A and B together? For instance I wanted to associate firstitem with the seconditem.
public interface IAlpha
{
[WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.Bare, RequestFormat = WebMessageFormat.Xml, ResponseFormat = WebMessageFormat.Xml, UriTemplate = "/AddBravoToAlpha/{firstitem}/{seconditem}")]
void AddBravoToAlpha(int firstitem, int seconditem);
}
public interface IBravo
{
// what goes in here?
}
public Class Alpha
{
public Alpha()
{
AlphaAdd = new List<Bravo>();
}
int Firstitem { get; set }
public List<Bravo> AlphaAdd { get; set; }
}
public Class Bravo
{
public Bravo()
{
BravoAdd = new List<Alpha>(); //not sure if Bravo can access Alpha (derived class)
}
int Seconditem { get; set }
Guid Indexer { get; set }
public List<Alpha> BravoAdd { get; set; }
}
public Class BravoDoesAlpha : IBravo, IAlpha //????
{
List<Alpha> alpha = new List<Alpha>();
List<Bravo> bravo = new List<Bravo>();
public void AddBravoToAlpha(int firstitem, int seconditem)
{
var result = alpha.Where(n => String.Equals(n.Firstitem, firstitem)).FirstOrDefault();
var result1 = bravo.Where(n => String.Equals(n.Seconditem, seconditem)).FirstOrDefault();
if (result != null)
{
result.BravoAdd.Add(new Alpha() { Firstitem = firstitem });
}
if (result1 != null)
{
result1.AlphaAdd.Add(new Bravo() { Seconditem = seconditem });
}
}
}
Okay, so the question you are being asked is basically one about how to do a certain kind of refactoring known as "extracting" an interface.
This is one of the more easy refactorings to do and to understand if you understand interfaces vs. types.
All interfaces are types, but not all types are interfaces.
Now let's assume we are dealing in a world with two families of types: classes and interfaces (as in your example).
Instead of working your example directly, I will work a different but clearer example that does not use Alpha, Bravo, Charlie, Epsilon, etc. because this kind of stuff makes it harder to see the meaning.
First, here's the before:
public class Dog
{
public void Bark() { Console.WriteLine("Woof!"); }
public int NumberOfDogLegs { get { return 2; } }
public int NumberOfDogFriends { get; set; } // this can be set
private string SecretsOfDog { get; set; } // this is private
}
public class DoorBell
{
public void Chime() { Console.WriteLine("Ding!"); }
}
To extract the interface of a class, simply, well, extract all the public members of the class to an interface.
public interface IDog
{
void Bark();
int NumberOfDogLegs { get; }
int NumberOfDogFriends { get; set; }
}
public interface IDoorBell
{
void Chime();
}
Now to really make use of OOP, you can find a way to abstract IDog and IDoorBell. What do they have in common? Well, the obvious one is they both make a noise. So we make a new interface, public interface IMakeANoise and say that IDog and IDoorBell both implement it.
public interface IMakeANoise
{
void MakeNoise();
}
public interface IDog : IMakeANoise
{
void Bark();
int NumberOfDogLegs { get; }
int NumberOfDogFriends { get; set; }
}
public interface IDoorBell : IMakeANoise
{
void Chime();
}
And now we have a new method to implement on Dog and DoorBell.
public class Dog : IDog
{
public void Bark() { Console.WriteLine("Woof!"); }
public int NumberOfDogLegs { get { return 2; } }
public int NumberOfDogFriends { get; set; } // this can be set
private string SecretsOfDog { get; set; } // this is private
public void IMakeANoise() { Bark(); }
}
public class DoorBell : IDoorBell
{
public void Chime() { Console.WriteLine("Ding!"); }
public void IMakeANoise() { Chime(); }
}
Now let's say we are actually writing a video game and Dog and DoorBell are both things that we can show on the screen. Well, this makes them a lot bigger because we will need to provide more information like their coordinates, their states, etc.
In this case, Dog and DoorBell may be very different to us but are similar enough to potentially merit sharing a base class. (Really, this is a stretch, but it does get the point across.)
Without adding all those new interfaces and their implementations, let's just do the "sharing a base class" refactoring for what we already have.
public class RenderableThing : IMakeANoise, IDoAThousandOtherThings
{
protected virtual string MyNoiseToMake { get { return ""; } }
public virtual void MakeANoise()
{
Console.WriteLine(MyNoiseToMake);
}
}
public class Dog : RenderableThing, IDog
{
protected override string MyNoiseToMake { get { return "Woof!"; } }
public void Bark() { MakeANoise(); } // see what we did there?
// Notice that I am not declaring the method MakeANoise because it is inherited and I am using it by overriding MyNoiseToMake
public int NumberOfDogLegs { get { return 2; } }
public int NumberOfDogFriends { get; set; } // this can be set
private string SecretsOfDog { get; set; } // this is private
}
public class DoorBell : RenderableThing, IDoorBell
{
public void Chime() { Console.WriteLine("Ding!"); }
public override void MakeANoise()
{
Chime(); Chime(); Chime(); //I'll do it my own way!
}
}
You may wonder, what's the point? So we can do this...
IMakeANoise dogNoiseMaker = new Dog();
IMakeANoise doorBellNoiseMaker = new DoorBell();
IList<IMakeANoise> listOfNoiseMakers = new List<IMakeANoise>();
listOfNoiseMakers.Add(dogNoiseMaker);
listOfNoiseMakers.Add(doorBellNoiseMaker);
foreach (IMakeANoise noiseMaker in listOfNoiseMakers)
{
noiseMaker.MakeANoise();
}
// This will output
// Woof!
// Ding!
// Ding!
// Ding!
I'm going to take a shot in the dark and venture a guess that you don't quite understand what interfaces and inheritance is. I'll start off by explaining what interfaces are:
Interfaces contain only the definitions of methods, properties, events or indexers that an inheriting class must implement.
For example:
interface IExample
{
void HelloWorld();
}
class ExampleClass : IExample
{
public void HelloWorld()
{
Console.WriteLine("Hello world.");
}
}
Now for Inheritance; when you derive a class from a base class the derived class will inherit all members of the base class except for the constructors. Note: Depending on the accessibility of the members in the base class it's children may or may not be able to access the parents members.
public class Animal
{
public string Name { get; set; }
public Animal(string name)
{
Name = name;
}
public void Talk()
{
Console.WriteLine("{0} is talking", Name);
}
}
public class Cat : Animal
{
public Cat(string name) : base(name) { }
}
public class Dog : Animal
{
public string FurColor { get; set; }
public Dog(string name, string furColor) : base(name)
{
FurColor = furColor;
}
public void Greeting()
{
Console.WriteLine("{0} has {1} fur.", Name, FurColor);
}
}
class Program
{
static void Main(string[] args)
{
var cat = new Cat("Rex");
cat.Talk();
var dog = new Dog("Beanie", "Red");
dog.Talk();
}
}
I often end up writing classes like this:
public class Animal
{
public string Colour { get; set; }
public int Weight { get; set; }
public Animal(Dog data)
{
this.Colour = data.Colour;
this.Weight = data.Weight;
}
public Animal(Cat data)
{
this.Colour = data.Colour;
this.Weight = data.Weight;
}
}
When you have lots of properties and types then you quickly end up with a lot of boiler plate code. Ideally in this situation I would just create an IAnimal interface and reference that. I'm currently in a situation where the Dog and Cat classes exist in a third party assembly and I can't modify them. The only solution that I can come up with is:
public class Animal
{
public string Colour { get; set; }
public int Weight { get; set; }
public Animal(Cat data){Init(data);}
public Animal(Dog data){Init(data);}
private void Init(dynamic data)
{
this.Colour = data.Colour;
this.Weight = data.Weight;
}
}
This works but I lose all type safety, is there a better solution than constructor injection?
Thanks,
Joe
EDIT: Here is a real world example. I have a third party library which returns 3 objects called:
GetPageByIdResult
GetPagesByParentIdResult
GetPagesByDateResult
(These are all auto generated classes from a service reference and the properties are pretty much identical)
Instead of dealing with these three objects I want to deal with a single PageData object or a collection of them.
You can have the logic in one common constructor that all the other constructors call:
public class Animal
{
public string Colour { get; set; }
public int Weight { get; set; }
public Animal(Dog data) : this (data.Colour, data.Weight)
{
}
public Animal(Cat data) : this (data.Colour, data.Weight)
{
}
private Animal(string colour, int weight)
{
this.Colour = colour;
this.Weight = weight;
}
}
This is pretty similar to your second solution but it doesn't lose type safety.
I'm currently in a situation where the Dog and Cat classes exist in a
third party assembly and I can't modify them
I'd suggest Automapper-based solution:
public static class AnimalFactory
{
public static Animal Create<T>(T source)
where T : class
{
Mapper.CreateMap<T, Animal>();
return Mapper.Map<Animal>(source);
}
}
Usage:
var catAnimal = AnimalFactory.Create(cat);
var dogAnimal = AnimalFactory.Create(dog);
Of course, you can provide a way to custom mapping configuration, if needed.
If you do not want to have the class littered like that you can try Extension methods?
public static Animal ToAnimal(this Dog item)
{
return new Animal() {Weight = item.Weight, Colour = item.Colour};
}
public static Animal ToAnimal(this Cat item)
{
return new Animal() {Weight = item.Weight, Colour = item.Colour};
}
try using json serializer's, with that we can ensure type safety.
public class Animal
{
public string Colour { get; set; }
public long Weight { get; set; }
public string Name { get; set; }
public Animal Create<T>(T anyType)
{
return GetObject<T, Animal>(anyType);
}
public K GetObject<T, K>(T type1)
{
try
{
var serialized = JsonConvert.SerializeObject(type1);
return JsonConvert.DeserializeObject<K>(serialized);
}
catch (Exception ex)
{
return default(K);
}
}
}
class Program
{
public static void Main(string[] args)
{
Animal obj = new Animal();
var animal = obj.Create(new { Colour = "Red", Weight = 100 });
//here you can pass any object, only same name properties will be initialized..
Console.WriteLine(animal.Colour + " : " + animal.Weight);
Console.ReadKey();
}
}
I have this class :
public class Person : ICloneable
{
public string FirstName { get; set; }
public string LastName { get; set; }
public object Clone()
{
return this;
}
}
An extension method :
public static class MyHelper
{
public static IEnumerable<T> Clone<T>(this IEnumerable<T> collection) where T : ICloneable
{
return collection.Select(item => (T)item.Clone());
}
}
I'd like use it in this case :
var myList = new List<Person>{
new Person { FirstName = "Dana", LastName = "Scully" },
new Person{ FirstName = "Fox", LastName = "Mulder" }
};
List<Person> myCopy = myList.Clone().ToList<Person>();
When I change in the "immediat window" a value of myCopy, there is a change in the orginial list too.
I'd like have both list completely independent
I missed something ?
Your implementation of Clone is wrong.
Try this:
public object Clone()
{
return MemberwiseClone();
}
Your clone method returns the same object.
You should implement it like this
public class Person : ICloneable
{
public string FirstName { get; set; }
public string LastName { get; set; }
public object Clone()
{
return new Person { FirstName = this.FirstName, LastName = this.LastName };
}
}
Apart from the issue with your Clone method inside your Person class you need to return a new list in your extension method also
return collection.Select(item => (T)item.Clone()).ToList();
This is because the Select method is from Linq which uses deferred execution. If you change the original list then the list of 'myCopy' will also change.