108 lines
2.8 KiB
Markdown
108 lines
2.8 KiB
Markdown
|
---
|
||
|
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).
|