Skip to content

Instantly share code, notes, and snippets.

@Sathyaish
Created August 2, 2015 07:16
Show Gist options
  • Save Sathyaish/d1d38e401aa485f642a7 to your computer and use it in GitHub Desktop.
Save Sathyaish/d1d38e401aa485f642a7 to your computer and use it in GitHub Desktop.
using System;
using System.Linq;
using System.Reflection;
namespace NullObjectDesignPattern
{
class Program
{
static void Main(string[] args)
{
// parameterless -- falls back to default dog
var dogFactory = new Factory<Dog>(new Dog { Name = "Tommy" });
var dog1 = dogFactory.Create<Dog>("Bruno");
Console.WriteLine(dog1.Name);
// parameterless -- overrides default dog
var dog2 = dogFactory.Create<Dog>();
Console.WriteLine(dog2.Name);
// parameterless -- falls back to default Cat
var catFactory = new Factory<Cat>(new Cat("Lisa"));
var cat1 = catFactory.Create<Cat>();
Console.WriteLine(cat1.Name);
// parameterized -- overrides default Cat
var cat2 = catFactory.Create<Cat>("Polly");
Console.WriteLine(cat2.Name);
// parameterized -- falls back to default Dog but creates a more derived type
var dog3 = dogFactory.Create<Poodle>();
Console.WriteLine($"Name: {dog3.Name}, Type {dog3.GetType().Name}");
// parameterized -- overrides default Dog
var dog4 = dogFactory.Create<Poodle>();
Console.WriteLine($"Name: {dog4.Name}, Type {dog4.GetType().Name}");
Console.ReadKey();
}
}
class Factory<T> where T: class
{
private T _defaultValue = default(T);
public Factory(T defaultValue = default(T))
{
_defaultValue = defaultValue;
}
public T Create<Derived>(params object[] args) where Derived : T
{
return TryCreate<Derived>(args) ?? _defaultValue;
}
protected virtual T TryCreate<Derived>(params object[] args) where Derived : T
{
var matchingCtor = (from ctor in typeof(Derived).GetConstructors()
let parameters = ctor.GetParameters()
where parameters.Length == args.Length
where parameters.AndArgumentTypesAreSame(args)
select ctor).FirstOrDefault();
if (matchingCtor == null) return null;
return matchingCtor.Invoke(args) as T;
}
}
public static class Extensions
{
public static bool AndArgumentTypesAreSame(this ParameterInfo[] parameterInfoArray, object[] argumentArray)
{
if (parameterInfoArray != null && argumentArray != null && parameterInfoArray.Length == argumentArray.Length)
{
for(int i = 0; i < parameterInfoArray.Length; i++)
{
if (parameterInfoArray[i].ParameterType != argumentArray[i].GetType())
return false;
}
return true;
}
return false;
}
}
class Dog
{
public string Name { get; set; } = "Woofy";
}
class Poodle : Dog { }
class Cat
{
public string Name { get; set; }
public Cat(string name)
{
Name = name;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment