I have a class that has some derived classes. That works.
I want to instantiate the "parent" class. Got that far...
But I want to instantiate it with one of the "child" classes, and then possibly change that "child" class later. Maybe the deriving is inappropriate here.
Take the following example:
public class Unicorn {
public string Horn { get; set; }
public Unicorn(){
}
}
public class BadUnicorn : Unicorn{
public string Rainbow()
{
return "dark rainbow";
}
}
public class GoodUnicorn : Unicorn{
public string Rainbow()
{
return "light rainbow";
}
}
I could instantiate one of the children, but then if I change one from "good" to "bad", I would have to re-instantiate. And maybe that's just the way it is, and that would be an acceptable answer if that's all there is to it.
I rather want to instantiate a Unicorn, and then be able to change it from Good to Bad to maintain information stored on that Unicorn, but have access to the current methods and properties of the "child" class.
That way when I call Unicorn.Rainbow() it calls the desired method of the "child" class.
I'm a little new to C#, is there a pattern that fits this bill?
You can't do what you want with polymorphism. You cannot change an instance of class from one to another. Once it is created it is always the same type.
You can use composition though.
Here's what you'd need to do:
public class Unicorn
{
public string Horn { get; set; }
public Unicorn(Rainbow rainbow)
{
_rainbow = rainbow;
}
public void SetRainbow(Rainbow rainbow)
{
_rainbow = rainbow;
}
private Rainbow _rainbow;
public string Rainbow()
{
return _rainbow.Colour();
}
}
public abstract class Rainbow
{
public abstract string Colour();
}
public class BadRainbow : Rainbow
{
public override string Colour()
{
return "dark rainbow";
}
}
public class GoodRainbow : Rainbow
{
public override string Colour()
{
return "light rainbow";
}
}
You can test like this:
var unicorn = new Unicorn(new GoodRainbow());
Console.WriteLine(unicorn.Rainbow());
unicorn.SetRainbow(new BadRainbow());
Console.WriteLine(unicorn.Rainbow());
This outputs:
light rainbow
dark rainbow
The instance of Unicorn stays the same, but you can change the rainbow.
Here's my take on delegate dictionary. While it seems superfluous to use Func instead of just string, if the method have additional functionality like calculation or need parameters, you're covered with Func.
public class Unicorn
{
static Dictionary<Attitude, Func<string>> RainbowByAttitude =
new Dictionary<Attitude, Func<string>>()
{
[Attitude.Bad] = new Func<string>(() => "dark rainbow"),
[Attitude.Good] = new Func<string>(()=>"light rainbow")
};
public string Horn { get; set; }
public enum Attitude
{
Good,Bad
}
public Attitude attitude;
public Unicorn(Attitude attitude)
{
this.attitude = attitude;
}
public string Rainbow() => RainbowByAttitude[attitude].Invoke();
}
class Program
{
static void Main(string[] args)
{
Unicorn unicorn;
unicorn = new Unicorn(Unicorn.Attitude.Bad);
Console.WriteLine(unicorn.Rainbow());
unicorn.attitude = Unicorn.Attitude.Good;
Console.WriteLine(unicorn.Rainbow());
}
}
It seems like a state pattern to me like this:
public abstract class UnicornState
{
public abstract UnicornState Change();
public abstract string Rainbow();
}
public sealed class GoodUnicornState : UnicornState
{
public override UnicornState Change()
{
return new BadUnicornState();
}
public override string Rainbow()
{
return "light rainbow";
}
}
public sealed class BadUnicornState : UnicornState
{
public override UnicornState Change()
{
return new GoodUnicornState();
}
public override string Rainbow()
{
return "dark rainbow";
}
}
public class Unicorn
{
public string Horn { get; set; }
public UnicornState State { get; set; }
public string Rainbow => State.Rainbow();
}
Usage:
var u = new Unicorn();
u.State = new GoodUnicornState();
Console.WriteLine(u.Rainbow);
u.State = u.State.Change();
Console.WriteLine(u.Rainbow);
Related
To cut down on reused code throughout my repository which gets values from another library, I wanted to create extension methods for "parsing"(for lack of a better word) one class to another. How do I implement abstract methods with different parameters.
I can't find anything that answers my question, and I'm not sure it can even be done.
Instead of having something like this in multiple places.
var list = _library.GetList();
var model = list.Select(o => new ClassA()
{
ID = o.ID,
Name = o.Name
}).ToList<ClassA>();
I want extension methods so I can call something like
var list = _library.GetList();
var model = ExtensionClass.ParseMany(list);
But, I want to base this off an abstract class so it can be reused by mutliple different classes, so I have
public abstract class Parser<U, T> where T : class where U : class
{
public abstract T ParseOne(U parser);
public abstract IEnumerable<T> ParseMany(IEnumerable<U> parser);
}
public class ParseA<ClassA, ClassADTO>
{
public override ClassA ParseOne(ClassADTO parser){ // }
}
But it doesn't seem that my parameter that is passed in is the actual object, it says it's a KeyValuePair and now I'm lost.
I expect to able to return a new instance based on my parameter, basically what I already do in my code multiple times.
I guess you can have a generic parser using Func. I just wrote a sample and hope it helps you.
public class ClassA
{
public int SomeNumber { get; set; }
public string SomeString { get; set; }
}
public class ClassB
{
public int OtherNumber { get; set; }
public string OtherString { get; set; }
}
public static class ExecuteParsingFunction
{
public static TDestiny Parse<TOrigin, TDestiny>(TOrigin origin,
Func<TOrigin, TDestiny> parserFunction)
{
return parserFunction(origin);
}
}
public static class ParsingFunctions
{
public static ClassB ParseAToB(ClassA a)
{
return new ClassB { OtherNumber = a.SomeNumber, OtherString = a.SomeString };
}
public static IEnumerable<ClassB> ParseManyAToB(IEnumerable<ClassA> aCollection)
{
foreach(var a in aCollection)
yield return ParseAToB(a);
}
}
public void Sample()
{
var a = new ClassA { SomeNumber = 1, SomeString = "Test" };
var manyAs = new List<ClassA> { a };
var b = ExecuteParsingFunction.Parse(a, ParserFunctions.ParseAToB);
var manyBs = ExecuteParsingFunction.Parse(manyAs, ParserFunctions.ParseManyAToB);
}
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 have the following base class:
public class Base
{
public string LogicalName { get; set; }
public int NumberOfChars { get; set; }
public Base()
{
}
public Base(string logicalName, int numberOfChars)
{
LogicalName = logicalName;
NumberOfChars = numberOfChars;
}
}
and the following derived classes:
public class Derived1 : Base
{
public const string EntityLogicalName = "Name1";
public const int EntityNumberOfChars = 30;
public Derived1() : base(EntityLogicalName, EntityNumberOfChars)
{
}
}
public class Derived2 : Base
{
public const string EntityLogicalName = "Name2";
public const int EntityNumberOfChars = 50;
public Derived2()
: base(EntityLogicalName, EntityNumberOfChars)
{
}
}
and I also have this function that is provided by a service:
public IEnumerable<T> GetEntities<T>(string entityName, int numberOfChars) where T : Base
{
//Some code to get the entities
}
My problem is how can I call this function generically? I want to call it with something that looks like this:
public void TestEntities<T>() where T : Base
{
var entities = GetEntities<T>(T.EntityLogicalName, T.EntityNumberOfChars);
//some other code to test the entities
}
This of course doesn't work because at this point T is not known. How can I accomplish something similar to this? EntityLogicalName and EntityNumberOfChars are characteristics that all Base derived classes have and they never change for each derived class. Can I get them from the Base class without instantiating objects or some other way that I am not seeing?
Replace constants with getter abstract properties
public abstract class Base
{
public abstract string LogicalName { get; }
public abstract int NumberOfChars { get; }
public Base()
{
}
}
public class Derived1 : Base
{
public string LogicalName { get { return "Name1"; } }
public int NumberOfChars { get { return 30; } }
public Derived1() : base()
{
}
}
Also, you will be able to put some logic into overriden getter, e.g. :
...
public string LogicalName { get { return this.EntityMap.Name; } }
...
UPDATE: The fact that you do not want to instantiate object from class but want to be able to get that string in a strongly typed manner can be handled in one more way. It is totally separate from answer above ( Since you can't override static props in c#). Consider the following code. We are adding one more class here, but LocatorInner can be a member of BaseClass. We are using this approach a lot in several existing apps.:
public class Locator
{
public static class LocatorInner<T> where T : BaseClass
{
public static string Name { get; set; }
}
public static string GetName<T>() where T : BaseClass
{
return LocatorInner<T>.Name;
}
public static void SetName<T>(string name) where T : BaseClass
{
LocatorInner<T>.Name = name;
}
}
public class BaseClass
{
}
public class DerivedClass: BaseClass
{
static DerivedClass()
{
Locator.LocatorInner<DerivedClass>.Name = "me";
}
}
public class TestClass<T> where T : BaseClass
{
public void Method()
{
var name = Locator.GetName<T>();
}
}
IMHO, I believe using constants here is a bad design decision.
You can either solve the issue using #vittore approach, but for me it sounds like you should use meta-programming with attributes if you're looking to get data from the T generic argument
For example, what about:
public class LogicalNameAttribute : Attribute
{
public LogicalNameAttribute(string name)
{
Name = name;
}
public string Name { get; private set; }
}
public class NumberOfCharsAttribute : Attribute
{
public NumberOfCharsAttribute (int number)
{
Number = number;
}
public string Number { get; private set; }
}
[LogicalName("Name1"), NumberOfChars(30)]
public class Derived1 : Base
{
public Derived1() : base()
{
}
}
Now your service method can extract attribute metadata as follows:
public void TestEntities<T>() where T : Base
{
LogicalNameAttribute logicalNameAttr = typeof(T).GetCustomAttribute<LogicalNameAttribute>();
NumberOfCharsAttribute numberOfCharsAttr = typeof(T).GetCustomAttribute<NumberOfCharsAttribute >();
Contract.Assert(logicalNameAttr != null);
Contract.Assert(numberOfCharsAttr != null);
string logicalName = logicalNameAttr.Name;
int numberOfChars = numberOfCharsAttr.Number;
// Other stuff
}
There's a performance penalty because you need to use reflection to get attributes applied to T, but you gain the flexibility of not forcing derived classes to provide this static info.
As #vittore mentioned, move the properties to base,pass the hard coded values from derived and in creation use just defautl(T)
public IEnumerable<T> GetEntities<T>(string entityName, int numberOfChars) where T : Base
{
yield return default(T); //Is its always class use new constraint and return new T();
}
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();
}
}
Hi
I have some problems in import scenarios example:
[Export(typeof(IICon))]
public class WriteInputData : IICon
{
[Import(typeof(IIOWriter))]
public IIOWriter IOWriter { get; set; }
public object Input { get; set; }
public void Process()
{
IOWriter.Write(Input);
}
}
Then i hawe two classes that implement interface IIOWriter like :
[Export(typeof(IIOWriter))]
public class FileWriter : IIOWriter
{
public string FilePath { get; set; }
public void Write(object data)
{
if (string.IsNullOrEmpty(FilePath))
FilePath = #"c:\test.txt";
var fl = new StreamWriter(FilePath, true);
fl.Write((string)data);
fl.Flush();
fl.Close();
}
public string Name
{
get { return "FileWriter"; }
}
}
[Export(typeof(IIOWriter))]
public class ConsoleWrite : IIOWriter
{
public void Write(object data)
{
Console.WriteLine((string)data);
}
public string Name
{
get { return "ConsoleWrite"; }
}
}
How can i let that to user so he can change that in runtime, so example whene he type select in ListBox FileWriter than the IIOWriter in WriteInputData will be injected FileWriter end so one..
Sorry for my bad english.
You probably need to supply some metadata to the export, such like:
[Export(typeof(IIOWriter)),
ExportMetadata("Name", "ConsoleWriter")]
public class ConsoleWriter : IIOWriter
{
}
The reason you need to do this, is that you need to know ahead of time what the user selection will match to. Because of this, you may want to refactor your design to remove the dependency on the IOWriter property:
[Export(typeof(IICon))]
public class WriteInputData : IICon
{
public object Input { get; set; }
public void Process(IIOWriter writer)
{
}
}
If you define your Process method to take in an instance, we can resolve it using the CompositionContainer. Firstly, define a metadata interface that matches your ExportMetadata value:
public interface INamedMetadata
{
string Name { get; }
}
And then, we can resolve the instance:
public IIOWriter GetWriter(string name)
{
return container
.GetExports<IIOWriter, INamedMetadata>()
.Where(e => e.Metadata.Name.Equals(name, StringComparison.OrdinalIgnoreCase))
.Select(e => e.Value)
.FirstOrDefault();
}
Hope that points you in the right direction....