RSCG – FactoryGenerator
generating DI code
This is how you can use FactoryGenerator .
The code that you start with is
<project sdk="Microsoft.NET.Sdk">
<propertygroup>
<outputtype>Exe</outputtype>
<targetframework>net8.0</targetframework>
<implicitusings>enable</implicitusings>
<nullable>enable</nullable>
</propertygroup>
<propertygroup>
<emitcompilergeneratedfiles>true</emitcompilergeneratedfiles>
<compilergeneratedfilesoutputpath>$(BaseIntermediateOutputPath)\GX</compilergeneratedfilesoutputpath>
</propertygroup>
<itemgroup>
<packagereference version="1.0.11" include="FactoryGenerator">
<packagereference version="1.0.11" include="FactoryGenerator.Attributes">
</packagereference>
</packagereference>
The code that you will use is
using InjectDemo;
InjectDemo.Generated.DependencyInjectionContainer sc = new();
var db = sc.Resolve<idatabase>();
db.Open();
using FactoryGenerator.Attributes;
namespace InjectDemo;
[Inject, Scoped]
public partial class Database : IDatabase
{
private readonly DatabaseCon con;
public Database(DatabaseCon con)
{
this.con = con;
}
public void Open()
{
Console.WriteLine($"open {con.Connection}");
this.con.Open();
}
}
using FactoryGenerator.Attributes;
namespace InjectDemo;
[Inject,Scoped, Self]
public partial class DatabaseCon: IDatabase
{
public string? Connection { get; set; }
public void Open()
{
Console.WriteLine("open" + Connection);
}
}
The code that is generated is
using System;
using System.Collections.Generic;
using FactoryGenerator;
using System.CodeDom.Compiler;
namespace InjectDemo.Generated;
#nullable enable
public partial class DependencyInjectionContainer
{
public DependencyInjectionContainer()
{
m_lookup = new(2)
{
{ typeof(InjectDemo.IDatabase),InjectDemo_IDatabase },
{ typeof(InjectDemo.DatabaseCon),InjectDemo_DatabaseCon },
};
}
public ILifetimeScope BeginLifetimeScope()
{
var scope = new LifetimeScope(this);
resolvedInstances.Add(new WeakReference<idisposable>(scope));
return scope;
}
}
using System;
using System.Collections.Generic;
using FactoryGenerator;
using System.CodeDom.Compiler;
namespace InjectDemo.Generated;
#nullable enable
public partial class DependencyInjectionContainer
{
internal InjectDemo.DatabaseCon InjectDemo_DatabaseCon()
{
if (m_InjectDemo_DatabaseCon != null)
return m_InjectDemo_DatabaseCon;
lock (m_lock)
{
if (m_InjectDemo_DatabaseCon != null)
return m_InjectDemo_DatabaseCon;
return m_InjectDemo_DatabaseCon = new InjectDemo.DatabaseCon();
}
}
internal InjectDemo.DatabaseCon? m_InjectDemo_DatabaseCon;
internal InjectDemo.Database InjectDemo_Database()
{
if (m_InjectDemo_Database != null)
return m_InjectDemo_Database;
lock (m_lock)
{
if (m_InjectDemo_Database != null)
return m_InjectDemo_Database;
return m_InjectDemo_Database = new InjectDemo.Database(InjectDemo_DatabaseCon());
}
}
internal InjectDemo.Database? m_InjectDemo_Database;
internal InjectDemo.IDatabase InjectDemo_IDatabase() => InjectDemo_Database();
}
using System;
using System.Collections.Generic;
using FactoryGenerator;
using System.CodeDom.Compiler;
namespace InjectDemo.Generated;
#nullable enable
public partial class DependencyInjectionContainer
{
}
using System;
using System.Collections.Generic;
using FactoryGenerator;
using System.CodeDom.Compiler;
namespace InjectDemo.Generated;
#nullable enable
[GeneratedCode("FactoryGenerator", "1.0.0")]
#nullable disable
public sealed partial class DependencyInjectionContainer : IContainer
{
private object m_lock = new();
private Dictionary<type ,func><object>> m_lookup; private readonly List<WeakReference<IDisposable>> resolvedInstances = new(); public T Resolve<T>() { return (T)Resolve(typeof(T)); } public object Resolve(Type type) { var instance = m_lookup[type](); return instance; } public void Dispose() { foreach (var weakReference in resolvedInstances) { if(weakReference.TryGetTarget(out var disposable)) { disposable.Dispose(); } } resolvedInstances.Clear(); } public bool TryResolve(Type type, out object resolved) { if(m_lookup.TryGetValue(type, out var factory)) { resolved = factory(); return true; } resolved = default; return false; } public bool TryResolve<T>(out T resolved) { if(m_lookup.TryGetValue(typeof(T), out var factory)) { var value = factory(); if(value is T t) { resolved = t; return true; } } resolved = default; return false; } public bool IsRegistered(Type type) { return m_lookup.ContainsKey(type); } public bool IsRegistered<T>() => IsRegistered(typeof(T)); }
using System; using System.Collections.Generic; using FactoryGenerator; using System.CodeDom.Compiler; namespace InjectDemo.Generated; #nullable enable public partial class LifetimeScope { public LifetimeScope(DependencyInjectionContainer fallback) { m_fallback = fallback; m_lookup = new(2) { { typeof(InjectDemo.IDatabase),InjectDemo_IDatabase }, { typeof(InjectDemo.DatabaseCon),InjectDemo_DatabaseCon }, }; } }
using System; using System.Collections.Generic; using FactoryGenerator; using System.CodeDom.Compiler; namespace InjectDemo.Generated; #nullable enable public partial class LifetimeScope { internal InjectDemo.DatabaseCon InjectDemo_DatabaseCon() { if (m_InjectDemo_DatabaseCon != null) return m_InjectDemo_DatabaseCon; lock (m_lock) { if (m_InjectDemo_DatabaseCon != null) return m_InjectDemo_DatabaseCon; return m_InjectDemo_DatabaseCon = new InjectDemo.DatabaseCon(); } } internal InjectDemo.DatabaseCon? m_InjectDemo_DatabaseCon; internal InjectDemo.Database InjectDemo_Database() { if (m_InjectDemo_Database != null) return m_InjectDemo_Database; lock (m_lock) { if (m_InjectDemo_Database != null) return m_InjectDemo_Database; return m_InjectDemo_Database = new InjectDemo.Database(InjectDemo_DatabaseCon()); } } internal InjectDemo.Database? m_InjectDemo_Database; internal InjectDemo.IDatabase InjectDemo_IDatabase() => InjectDemo_Database(); }
using System; using System.Collections.Generic; using FactoryGenerator; using System.CodeDom.Compiler; namespace InjectDemo.Generated; #nullable enable public partial class LifetimeScope { }
using System; using System.Collections.Generic; using FactoryGenerator; using System.CodeDom.Compiler; namespace InjectDemo.Generated; #nullable enable [GeneratedCode("FactoryGenerator", "1.0.0")] #nullable disable public sealed partial class LifetimeScope : IContainer { public ILifetimeScope BeginLifetimeScope() { var scope = m_fallback.BeginLifetimeScope(); resolvedInstances.Add(new WeakReference<IDisposable>(scope)); return scope; } private object m_lock = new(); private DependencyInjectionContainer m_fallback; private Dictionary<Type,Func<object>> m_lookup; private readonly List<WeakReference<IDisposable>> resolvedInstances = new(); public T Resolve<T>() { return (T)Resolve(typeof(T)); } public object Resolve(Type type) { var instance = m_lookup[type](); return instance; } public void Dispose() { foreach (var weakReference in resolvedInstances) { if(weakReference.TryGetTarget(out var disposable)) { disposable.Dispose(); } } resolvedInstances.Clear(); } public bool TryResolve(Type type, out object resolved) { if(m_lookup.TryGetValue(type, out var factory)) { resolved = factory(); return true; } resolved = default; return false; } public bool TryResolve<T>(out T resolved) { if(m_lookup.TryGetValue(typeof(T), out var factory)) { var value = factory(); if(value is T t) { resolved = t; return true; } } resolved = default; return false; } public bool IsRegistered(Type type) { return m_lookup.ContainsKey(type); } public bool IsRegistered<T>() => IsRegistered(typeof(T)); }
Code and pdf at https://ignatandrei.github.io/RSCG_Examples/v2/docs/FactoryGenerator