167 lines
5.1 KiB
C#
167 lines
5.1 KiB
C#
// Copyright (C) 2025 Michael Becker <alcexhim@gmail.com>
|
|
//
|
|
// This file is part of Mocha.NET.
|
|
//
|
|
// Mocha.NET is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// Mocha.NET is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with Mocha.NET. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
|
|
using System.Reflection;
|
|
using System.Text;
|
|
using MBS.Core.Reflection;
|
|
using Microsoft.CodeAnalysis;
|
|
using Microsoft.CodeAnalysis.CSharp;
|
|
using Microsoft.CodeAnalysis.Emit;
|
|
using Mocha.Core;
|
|
using Mocha.Core.Oop;
|
|
using Mocha.Modeling.CodeGeneration;
|
|
using Mocha.Modeling.CodeGeneration.Generators;
|
|
|
|
namespace Mocha.Modeling;
|
|
|
|
public class OmsObjectFactory<TOmsClass> : CSharpCodeGenerator where TOmsClass : IOmsItem
|
|
{
|
|
public TOmsClass CreateDatabase(Oms oms)
|
|
{
|
|
string script = BuildScript();
|
|
Assembly dynamicAssembly = CompileScript(script, [ typeof(TOmsClass).Assembly.Location ]);
|
|
|
|
Type t = typeof(TOmsClass);
|
|
foreach (Type t2 in t.GetNestedTypes())
|
|
{
|
|
CreateType(oms, t2);
|
|
}
|
|
|
|
Type?[] tis;
|
|
try
|
|
{
|
|
tis = dynamicAssembly.GetTypes();
|
|
}
|
|
catch (ReflectionTypeLoadException ex)
|
|
{
|
|
tis = ex.Types;
|
|
}
|
|
|
|
object? o = Activator.CreateInstance(tis[0]);
|
|
if ((o?.GetType().IsAssignableTo(typeof(TOmsClass))).GetValueOrDefault())
|
|
{
|
|
TOmsClass db = (TOmsClass)o;
|
|
return db;
|
|
}
|
|
throw new TypeInitializationException(typeof(TOmsClass).Name, null);
|
|
}
|
|
public TOmsClass CreateInstance(Oms oms, Guid globalIdentifier)
|
|
{
|
|
string script = BuildScript(globalIdentifier);
|
|
Assembly dynamicAssembly = CompileScript(script, [ typeof(TOmsClass).Assembly.Location ]);
|
|
|
|
Type?[] tis;
|
|
try
|
|
{
|
|
tis = dynamicAssembly.GetTypes();
|
|
}
|
|
catch (ReflectionTypeLoadException ex)
|
|
{
|
|
tis = ex.Types;
|
|
}
|
|
|
|
object? o = Activator.CreateInstance(tis[0]);
|
|
tis[0].GetProperty("Oms", BindingFlags.Instance | BindingFlags.Public).SetValue(o, oms);
|
|
|
|
if ((o?.GetType().IsAssignableTo(typeof(TOmsClass))).GetValueOrDefault())
|
|
{
|
|
TOmsClass db = (TOmsClass)o;
|
|
return db;
|
|
}
|
|
throw new TypeInitializationException(typeof(TOmsClass).Name, null);
|
|
}
|
|
|
|
private void CreateType(Oms oms, Type t)
|
|
{
|
|
if (t.IsInterface)
|
|
{
|
|
string name = OmsDatabase.GetNameForClass(t);
|
|
Guid id = OmsDatabase.GetGlobalIdentifierForClass(t);
|
|
|
|
oms.CreateClass(name, id);
|
|
}
|
|
}
|
|
|
|
private string BuildScript(Guid? globalIdentifier = null)
|
|
{
|
|
Type t = typeof(TOmsClass);
|
|
|
|
Namespace ns = new Namespace(new string[] { "Mocha", "Modeling", "Models", t.Name });
|
|
|
|
|
|
if (t.IsAssignableTo(typeof(IOmsDatabase)))
|
|
{
|
|
Mocha.Modeling.CodeGeneration.Class cl = GenerateDatabase(t);
|
|
ns.Items.Add(cl);
|
|
}
|
|
else
|
|
{
|
|
Mocha.Modeling.CodeGeneration.Class cl = GenerateClass(t, globalIdentifier);
|
|
ns.Items.Add(cl);
|
|
}
|
|
|
|
return GenerateCode(ns);
|
|
}
|
|
|
|
private Mocha.Modeling.CodeGeneration.Class GenerateDatabase(Type t)
|
|
{
|
|
Mocha.Modeling.CodeGeneration.Class cl = new CodeGeneration.Class();
|
|
cl.Name = t.Name;
|
|
cl.InheritsClass = ParseObjectReference(SafeTypeName(t));
|
|
|
|
Type[] nts = t.GetNestedTypes();
|
|
foreach (Type nt in nts)
|
|
{
|
|
cl.Items.Add(GenerateClass(nt));
|
|
}
|
|
|
|
foreach (PropertyInfo pi in t.GetProperties(BindingFlags.Public | BindingFlags.Instance))
|
|
{
|
|
cl.Items.Add(GenerateProperty(pi));
|
|
}
|
|
|
|
cl.Items.Add(new Property("Oms", new ObjectReference(new string[] { "Mocha", "Core", "Oms" }), null) { AccessModifier = CodeGeneration.AccessModifier.Public, UseAutoProperty = true, ReadOnly = false });
|
|
cl.Items.Add(new CodeGeneration.Method("Initialize", new MethodParameter[] { new MethodParameter("oms", new ObjectReference(["Mocha", "Core", "Oms"]))}, new IMethodMember[]
|
|
{
|
|
new PropertyAssignment(new ObjectReference(["this", "Oms"]), "oms")
|
|
}) { AccessModifier = CodeGeneration.AccessModifier.Public});
|
|
|
|
return cl;
|
|
}
|
|
|
|
private Mocha.Modeling.CodeGeneration.Class GenerateClass(Type t, Guid? globalIdentifier = null)
|
|
{
|
|
Mocha.Modeling.CodeGeneration.Class cl = new CodeGeneration.Class();
|
|
cl.Name = t.Name;
|
|
cl.InheritsClass = ParseObjectReference(SafeTypeName(t));
|
|
|
|
if (globalIdentifier == null)
|
|
{
|
|
globalIdentifier = OmsDatabase.GetGlobalIdentifierForClass(t);
|
|
}
|
|
|
|
cl.Items.Add(new Property("GlobalIdentifier", new ObjectReference(new string[] { "System", "Guid" }), new CreateInstance(["System", "Guid"], [globalIdentifier.ToString()])) { AccessModifier = CodeGeneration.AccessModifier.Public });
|
|
cl.Items.Add(new Property("Oms", new ObjectReference(new string[] { "Mocha", "Core", "Oms" }), null) { AccessModifier = CodeGeneration.AccessModifier.Public, UseAutoProperty = true, ReadOnly = false });
|
|
|
|
foreach (PropertyInfo pi in t.GetProperties(BindingFlags.Public | BindingFlags.Instance))
|
|
{
|
|
cl.Items.Add(GenerateProperty(pi));
|
|
}
|
|
return cl;
|
|
}
|
|
} |