HostFactory
using Autodesk.DesignScript.Geometry.Properties;
using Autodesk.DesignScript.Interfaces;
using Autodesk.DesignScript.Runtime;
using Dynamo.Events;
using Dynamo.Session;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Reflection;
using System.Threading;
namespace Autodesk.DesignScript.Geometry
{
[SupressImportIntoVM]
public class HostFactory
{
private static readonly HostFactory mSelf;
private readonly IGeometryFactory mGeometryFactory;
private readonly IPersistenceManager mPersistenceManager;
private readonly List<IExtensionApplication> mExtensionApplications = new List<IExtensionApplication>();
private readonly List<Type> mExtensionApplicationTypes = new List<Type>();
private string mErrorString = string.Empty;
private ConcurrentDictionary<int, ConcurrentBag<DesignScriptEntity>> itemsToDelete = new ConcurrentDictionary<int, ConcurrentBag<DesignScriptEntity>>();
private double scaleFactor = 1;
public static HostFactory Instance => mSelf;
internal double ScaleFactor {
get {
return scaleFactor;
}
set {
scaleFactor = value;
}
}
internal static bool ExtensionApplicationStarted { get; set; }
public static IGeometryFactory Factory {
get {
if (Instance.mGeometryFactory == null) {
if (string.IsNullOrEmpty(Instance.mErrorString))
Instance.mErrorString = Resources.NoImplementationException;
throw new NotImplementedException(Instance.mErrorString);
}
return Instance.mGeometryFactory;
}
}
public static IPersistenceManager PersistenceManager => Instance.mPersistenceManager;
internal static List<IExtensionApplication> ExtensionApplications => Instance.mExtensionApplications;
static HostFactory()
{
mSelf = new HostFactory();
}
private HostFactory()
{
try {
WorkspaceEvents.WorkspaceSettingsChanged += WorkspaceSettingsChanged;
ExecutionEvents.GraphPostExecution += ExecutionEvents_GraphPostExecution;
string factoryFilePath = null;
bool flag = GetFactoryFileFromSessionConfig(ref factoryFilePath);
if (!flag)
flag = GetFactoryFileFromGeometryConfig(ref factoryFilePath);
if (flag && !string.IsNullOrEmpty(factoryFilePath))
factoryFilePath = GeometryExtension.LocateFile(factoryFilePath);
if (mGeometryFactory == null && !string.IsNullOrEmpty(factoryFilePath))
mGeometryFactory = (CreateInstance(typeof(IGeometryFactory), factoryFilePath) as IGeometryFactory);
if (!ExtensionApplicationStarted && mExtensionApplications.Count > 0) {
foreach (IExtensionApplication mExtensionApplication in mExtensionApplications) {
mExtensionApplication.OnBeginExecution(Application.Instance.Session);
}
ExtensionApplicationStarted = true;
}
} catch (Exception ex) {
Exception innerException = ex.InnerException;
mErrorString = ex.Message;
}
}
public void StartUp(double scaleFactor = 1)
{
this.scaleFactor = scaleFactor;
foreach (IExtensionApplication mExtensionApplication in mExtensionApplications) {
mExtensionApplication.StartUp(default(ExtensionStartupParams));
}
}
public void ShutDown()
{
foreach (IExtensionApplication mExtensionApplication in mExtensionApplications) {
mExtensionApplication.ShutDown();
}
}
public void PreloadAsmLibraries(string baseDirectory)
{
foreach (IExtensionApplication mExtensionApplication in mExtensionApplications) {
mExtensionApplication.PreloadAsmLibraries(baseDirectory);
}
}
internal void MarkDSEntityForDisposal(DesignScriptEntity entity)
{
ConcurrentBag<DesignScriptEntity> orAdd = itemsToDelete.GetOrAdd(entity.constructorThreadId, new ConcurrentBag<DesignScriptEntity>());
orAdd.Add(entity);
}
internal void clearPendingDisposals()
{
int managedThreadId = Thread.CurrentThread.ManagedThreadId;
if (itemsToDelete.TryGetValue(managedThreadId, out ConcurrentBag<DesignScriptEntity> value)) {
while (!value.IsEmpty) {
if (value.TryTake(out DesignScriptEntity result))
result.Dispose();
}
}
}
private void ExecutionEvents_GraphPostExecution(Dynamo.Session.IExecutionSession session)
{
clearPendingDisposals();
}
private void WorkspaceSettingsChanged(WorkspacesSettingsChangedEventArgs args)
{
ScaleFactor = args.ScaleFactor;
}
private static bool GetFactoryFileFromGeometryConfig(ref string factoryFilePath)
{
IProtoGeometryConfiguration settings = ProtoGeometryConfigurationManager.Settings;
if (settings != null)
factoryFilePath = settings.GeometryFactoryFileName;
return !string.IsNullOrEmpty(factoryFilePath);
}
private static bool GetFactoryFileFromSessionConfig(ref string factoryFilePath)
{
Autodesk.DesignScript.Interfaces.IExecutionSession session = Application.Instance.Session;
if (session == null)
return false;
IConfiguration configuration = session.Configuration;
if (configuration == null)
return false;
factoryFilePath = (configuration.GetConfigValue(ConfigurationKeys.GeometryFactory) as string);
return !string.IsNullOrEmpty(factoryFilePath);
}
private object CreateInstance(Type type, string library)
{
object obj = null;
Type type2 = null;
Type typeFromHandle = typeof(IExtensionApplication);
Assembly assembly = Assembly.LoadFrom(library);
Type[] exportedTypes = assembly.GetExportedTypes();
Type[] array = exportedTypes;
foreach (Type type3 in array) {
if (!type3.IsAbstract) {
if (type.IsAssignableFrom(type3))
obj = Activator.CreateInstance(type3);
if (typeFromHandle.IsAssignableFrom(type3))
type2 = type3;
if ((Type)null != type2 && obj != null)
break;
}
}
if (obj != null && (Type)null != type2 && !mExtensionApplicationTypes.Contains(type2)) {
IExtensionApplication extensionApplication = Activator.CreateInstance(type2) as IExtensionApplication;
if (extensionApplication != null) {
mExtensionApplicationTypes.Add(type2);
mExtensionApplications.Add(extensionApplication);
}
}
return obj;
}
}
}