using System.Linq;
using System.Reflection;
using Artemis.Core;
using Ninject;
using Ninject.Parameters;
///
/// Represents a kind of node inside a containing storage value of type
/// and a view model of type .
///
/// The type of value the node stores
/// The type of view model the node uses
public abstract class Node : Node, ICustomViewModelNode where TViewModel : ICustomNodeViewModel
{
///
protected Node()
{
}
///
protected Node(string name, string description) : base(name, description)
{
}
[Inject]
internal IKernel Kernel { get; set; } = null!;
///
/// Called when a view model is required
///
///
public virtual TViewModel GetViewModel(NodeScript nodeScript)
{
// Limit to one constructor, there's no need to have more and it complicates things anyway
ConstructorInfo[] constructors = typeof(TViewModel).GetConstructors();
if (constructors.Length != 1)
throw new ArtemisCoreException("Node VMs must have exactly one constructor");
// Find the ScriptConfiguration parameter, it is required by the base constructor so its there for sure
ParameterInfo? configurationParameter = constructors.First().GetParameters().FirstOrDefault(p => GetType().IsAssignableFrom(p.ParameterType));
if (configurationParameter?.Name == null)
throw new ArtemisCoreException($"Couldn't find a valid constructor argument on {typeof(TViewModel).Name} with type {GetType().Name}");
return Kernel.Get(new ConstructorArgument(configurationParameter.Name, this), new ConstructorArgument("script", nodeScript));
}
///
/// Gets or sets the position of the node's custom view model.
///
public CustomNodeViewModelPosition ViewModelPosition { get; protected set; } = CustomNodeViewModelPosition.BetweenPinsTop;
///
///
public ICustomNodeViewModel GetCustomViewModel(NodeScript nodeScript)
{
return GetViewModel(nodeScript);
}
}