2023-03-11 17:11:40 +08:00
using System ;
using System.Collections.Generic ;
using System.Linq ;
using System.Reflection ;
using System.Runtime.CompilerServices ;
namespace DCFApixels.DragonECS
{
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = true)]
2023-03-12 01:33:48 +08:00
sealed class EcsRunnerFilterAttribute : Attribute
2023-03-11 17:11:40 +08:00
{
public readonly Type interfaceType ;
public readonly object filter ;
2023-03-12 01:33:48 +08:00
public EcsRunnerFilterAttribute ( Type interfaceType , object filter )
2023-03-11 17:11:40 +08:00
{
this . interfaceType = interfaceType ;
this . filter = filter ;
}
}
2023-03-12 01:33:48 +08:00
public interface IEcsProcessor { }
2023-03-11 17:11:40 +08:00
2023-03-12 01:33:48 +08:00
public static class IEcsProcessorExtensions
2023-03-11 17:11:40 +08:00
{
2023-03-12 01:33:48 +08:00
public static bool IsRunner ( this IEcsProcessor self )
2023-03-11 17:11:40 +08:00
{
2023-03-12 01:33:48 +08:00
return self is IEcsRunner ;
2023-03-11 17:11:40 +08:00
}
}
2023-03-12 02:02:39 +08:00
2023-03-12 01:33:48 +08:00
internal static class EcsRunnerActivator
2023-03-11 17:11:40 +08:00
{
2023-03-12 02:02:39 +08:00
private static Dictionary < Guid , Type > _runnerTypes ; //interface guid/ Runner type pairs;
static EcsRunnerActivator ( )
{
List < Exception > exceptions = new List < Exception > ( ) ;
Type runnerBaseType = typeof ( EcsRunner < > ) ;
List < Type > newRunnerTypes = new List < Type > ( ) ;
newRunnerTypes = Assembly . GetAssembly ( runnerBaseType )
. GetTypes ( )
. Where ( type = > type . BaseType ! = null & & type . BaseType . IsGenericType & & runnerBaseType = = type . BaseType . GetGenericTypeDefinition ( ) )
. ToList ( ) ;
#if DEBUG
for ( int i = 0 ; i < newRunnerTypes . Count ; i + + )
{
var e = CheckRunnerValide ( newRunnerTypes [ i ] ) ;
if ( e ! = null )
{
newRunnerTypes . RemoveAt ( i - - ) ;
exceptions . Add ( e ) ;
}
}
#endif
_runnerTypes = new Dictionary < Guid , Type > ( ) ;
foreach ( var item in newRunnerTypes )
{
Type intrf = item . GetInterfaces ( ) [ 2 ] ; //TODO доработать это место. В о -первых убрать магическое число 2, во-вторых сделать так чтоб брался только наследованный интерфейс, а не все
_runnerTypes . Add ( intrf . GUID , item ) ;
}
if ( exceptions . Count > 0 )
{
foreach ( var item in exceptions ) throw item ;
}
}
private static Exception CheckRunnerValide ( Type type ) //TODO доработать проверку валидности реалиазации ранера
{
if ( type . ReflectedType ! = null )
return new Exception ( $"{type.FullName}.ReflectedType must be Null, but equal to {type.ReflectedType.FullName}" ) ;
//var interfaces = type.GetInterfaces();
//if (interfaces.Length != 1 || interfaces[0].GUID != typeof())
//{
//}
return null ;
}
2023-03-11 17:11:40 +08:00
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2023-03-12 02:02:39 +08:00
public static void InitFor < TInterface > ( ) where TInterface : IEcsProcessor
2023-03-11 17:11:40 +08:00
{
2023-03-12 02:02:39 +08:00
Type interfaceType = typeof ( TInterface ) ;
Guid interfaceGuid = interfaceType . GUID ;
if ( ! _runnerTypes . TryGetValue ( interfaceGuid , out Type runnerType ) )
{
throw new Exception ( ) ;
}
if ( interfaceType . IsGenericType )
2023-03-11 17:11:40 +08:00
{
2023-03-12 02:02:39 +08:00
Type [ ] genericTypes = interfaceType . GetGenericArguments ( ) ;
runnerType = runnerType . MakeGenericType ( genericTypes ) ;
2023-03-11 17:11:40 +08:00
}
2023-03-12 02:02:39 +08:00
EcsRunner < TInterface > . Init ( runnerType ) ;
2023-03-11 17:11:40 +08:00
}
}
2023-03-12 01:33:48 +08:00
public interface IEcsRunner { }
public abstract class EcsRunner < TInterface > : IEcsProcessor , IEcsRunner
where TInterface : IEcsProcessor
2023-03-11 17:11:40 +08:00
{
internal static void Init ( Type subclass )
{
#if DEBUG | | DCFAECS_NO_SANITIZE_CHECKS
if ( _subclass ! = null )
{
throw new ArgumentException ( $"The Runner<{typeof(TInterface).FullName}> can only have one subclass" ) ;
}
Type interfaceType = typeof ( TInterface ) ;
var interfaces = interfaceType . GetInterfaces ( ) ;
if ( interfaceType . IsInterface = = false )
{
throw new ArgumentException ( $"{typeof(TInterface).FullName} is not interface" ) ;
}
2023-03-12 01:33:48 +08:00
if ( interfaces . Length ! = 1 | | interfaces [ 0 ] ! = typeof ( IEcsProcessor ) )
2023-03-11 17:11:40 +08:00
{
2023-03-12 01:33:48 +08:00
throw new ArgumentException ( $"{typeof(TInterface).FullName} does not directly inherit the {nameof(IEcsProcessor)} interface" ) ;
2023-03-11 17:11:40 +08:00
}
#endif
_subclass = subclass ;
}
2023-03-12 01:33:48 +08:00
public static TInterface Instantiate ( IEnumerable < IEcsProcessor > targets , object filter )
2023-03-11 17:11:40 +08:00
{
Type interfaceType = typeof ( TInterface ) ;
2023-03-12 02:02:39 +08:00
IEnumerable < IEcsProcessor > newTargets ;
2023-03-11 17:11:40 +08:00
if ( filter ! = null )
{
2023-03-12 02:02:39 +08:00
newTargets = targets . Where ( o = >
2023-03-11 17:11:40 +08:00
{
if ( o is TInterface = = false ) return false ;
2023-03-12 01:33:48 +08:00
var atr = o . GetType ( ) . GetCustomAttribute < EcsRunnerFilterAttribute > ( ) ;
2023-03-11 17:11:40 +08:00
return atr ! = null & & atr . interfaceType = = interfaceType & & atr . filter . Equals ( filter ) ;
} ) ;
}
else
{
2023-03-12 02:02:39 +08:00
newTargets = targets . Where ( o = >
2023-03-11 17:11:40 +08:00
{
if ( o is TInterface = = false ) return false ;
2023-03-12 01:33:48 +08:00
var atr = o . GetType ( ) . GetCustomAttribute < EcsRunnerFilterAttribute > ( ) ;
2023-03-11 17:11:40 +08:00
return atr = = null | | atr . interfaceType = = interfaceType & & atr . filter = = null ;
} ) ;
}
2023-03-12 02:02:39 +08:00
return Instantiate ( newTargets . Select ( o = > ( TInterface ) o ) . ToArray ( ) ) ;
2023-03-11 17:11:40 +08:00
}
2023-03-12 01:33:48 +08:00
public static TInterface Instantiate ( IEnumerable < IEcsProcessor > targets )
2023-03-11 17:11:40 +08:00
{
2023-03-12 02:02:39 +08:00
return Instantiate ( targets . Where ( o = > o is TInterface ) . Select ( o = > ( TInterface ) o ) . ToArray ( ) ) ;
2023-03-11 17:11:40 +08:00
}
internal static TInterface Instantiate ( TInterface [ ] targets )
{
2023-03-12 02:02:39 +08:00
if ( _subclass = = null )
EcsRunnerActivator . InitFor < TInterface > ( ) ;
2023-03-12 01:33:48 +08:00
var instance = ( EcsRunner < TInterface > ) Activator . CreateInstance ( _subclass ) ;
return ( TInterface ) ( IEcsProcessor ) instance . Set ( targets ) ;
2023-03-11 17:11:40 +08:00
}
private static Type _subclass ;
2023-03-12 02:02:39 +08:00
protected static void SetSublcass ( Type type ) = > _subclass = type ;
2023-03-11 17:11:40 +08:00
protected TInterface [ ] targets ;
2023-03-12 01:33:48 +08:00
private EcsRunner < TInterface > Set ( TInterface [ ] targets )
2023-03-11 17:11:40 +08:00
{
this . targets = targets ;
return this ;
}
}
}