mdk.fr/content/blog/a-justintime-class.md

108 lines
2.8 KiB
Markdown
Raw Normal View History

2017-04-04 21:11:23 +00:00
---
Title: A JustInTime class
---
I discovered in my code a redundant pattern :
:::csharp
private SomeType _something;
private SomeType something { get { if (_something == null) _something = new SomeType(....); return _something;} }
Usefull in Silverlight, when your Blender always say "Can't compile !
Strange errors ! but compiles when i comment your WebClient... in ctor
of that class..." So i use it to have members builded the first time
they are used, "Just in time". /!\\ It's not a Singleton ! i can have
others instance of this class new-ing it directly ! /!\\ Singleton is
Evil // feed the Troll So i factorized it :
:::csharp
public class Jit
{
T _instance;
object[] _ctor_params;
public Jit(object[] ctor_params)
{
_ctor_params = ctor_params;
}
public Jit()
{
}
public T create(object[] ctor_params)
{
Type[] param_types = ctor_params.Aggregate>(
new List(),
(List lt, object o) =>
{
lt.Add(o.GetType());
return lt;
}).ToArray();
var ctor = typeof(T).GetConstructor(param_types);
if (ctor == null)
throw new Exception(param_types.Aggregate(
"No constructor found for " + typeof(T).Name + " taking",
(string i, Type t) => { return i + " " + t.Name; }));
return (T)ctor.Invoke(_ctor_params);
}
public T create()
{
return (_ctor_params == null)
? create(new object[] { })
: create(_ctor_params);
}
public T single()
{
if (_instance == null)
_instance = create();
return _instance;
}
}
A usage demo:
:::csharp
public class Test
{
Test(string foo, int bar)
{
Console.WriteLine("Test ctor with : " + foo + " and " + bar);
}
public void foo()
{
Console.WriteLine("bar");
}
}
public partial class Page : UserControl
{
public event EventHandler my_event;
private Jit test = new Jit(new object[]{"42", 42});
public Page()
{
InitializeComponent();
// test is not yet built
test.single().foo(); // Whill build a Test and call foo()
test.single().foo(); // Whill call foo on the same Test.
}
}
So a:
:::csharp
private SomeType _something;
private SomeType something { get { if (_something == null) _something = new SomeType(....); return _something;} }
become:
:::csharp
private Jit something = new Jit(new object[]{...});
Note the Jit ctor, taking a array of objects, it's the objects to pass
to your ctor's class (found by reflection using their types).