/// <summary> /// Recherche du processor associé à la commande (Création si il n'existe pas) /// Cet appel est thread-safe /// </summary> /// <param name="commandType">Type de la commande</param> /// <returns></returns> private CommandProcessorInfo GetCommandProcessor(Type commandType) { DebugContract.Requires(commandType); CommandProcessorInfo info; var key = commandType.FullName; if (!_commandProcessors.TryGetValue(key, out info)) { lock (_commandProcessors) { if (!_commandProcessors.TryGetValue(key, out info)) { // Defaut processor pour le type 'commandtype' info = new CommandProcessorInfo(); info.RunProcessor = CreateProcessor(commandType, info); _commandProcessors.Add(key, info); } } } return(info); }
private void PrepareProcessor(CommandProcessorInfo processorInfo) { if (processorInfo.IsPrepared) { return; } processorInfo.Processor.ClearInterceptors(); foreach (var item in _interceptors) { var ruleCommandType = item.Key; if (!ReflectionHelper.IsAssignableFrom(ruleCommandType, processorInfo.CommandType)) { continue; } foreach (var info in item.Value) { var i = info.CommandType == processorInfo.CommandType ? info.Interceptor : new InterceptorWrapper(info.CommandType, info.Interceptor); processorInfo.Processor.RegisterInterceptor(i, info.Priority); } processorInfo.IsPrepared = true; } }
/// <summary> /// Création de l'appel du processor. Consiste à générer une appel générique typé à partir du type fourni /// </summary> /// <param name="commandType">Type de la commande</param> /// <param name="info"></param> /// <returns></returns> private Func <ISession, ISessionContext, IDomainCommand, ContinuationStatus> CreateProcessor(Type commandType, CommandProcessorInfo info) { DebugContract.Requires(commandType); DebugContract.Requires(info); // p = new CommandProcessor<commandtype>() var processorType = typeof(CommandProcessor <>).MakeGenericType(commandType); info.Processor = Activator.CreateInstance(processorType, _domainModel.Store) as ICommandProcessor; info.CommandType = commandType; // new ExecutionCommandContext<commandType>(s,c) var contextType = typeof(ExecutionCommandContext <>).MakeGenericType(commandType); // Création du type générique voulu // Recherche du constructeur de ce nouveau type pour pouvoir l'instancier var contextCtor = ReflectionHelper.GetProtectedConstructor(contextType, new[] { typeof(ISession), typeof(ISessionContext), commandType }); // Génération en dynamique d'un appel en utilisant un contexte typé var psession = Expression.Parameter(typeof(ISession)); var pcommand = Expression.Parameter(typeof(IDomainCommand)); var plog = Expression.Parameter(typeof(ISessionContext)); // p.RunProcessor = (s, log, c) => p.Process(new ExecutionCommandContext<commandType>(s,log, c)) var invocationExpression = Expression.Lambda(Expression.Block(Expression.Call(Expression.Convert(Expression.Constant(info.Processor), processorType), // p ReflectionHelper.GetMethod(processorType, "Process") .First(), // .Process Expression.New(contextCtor, psession, plog, Expression.Convert(pcommand, commandType)) // new ExecutionCommandContext<commandType>(s,log, c) )), psession, plog, pcommand); // (s, log, c) return((Func <ISession, ISessionContext, IDomainCommand, ContinuationStatus>)invocationExpression.Compile()); }