我正在嘗試使用類似於CQRS中使用的命令模式的Azure消息隊列。使用Ninject查找適當的CommandHandler
下面是一個例子命令:
public class SetZoneModeCommand : ICommand
{
public string GatewayId { get; set; }
public string ReceiverId { get; set; }
public int ChannelNumber { get; set; }
public HeatingMode Mode { get; set; }
}
這裏是它的處理器
public class SetZoneModeCommandHandler : ICommandHandler<SetZoneModeCommand>
{
private readonly IDatabaseContext _databaseContext;
public SetZoneModeCommandHandler(IDatabaseContext databaseContext)
{
_databaseContext = databaseContext;
}
public RequestStatus Execute(SetZoneModeCommand command)
{
if (command == null)
{
throw new ArgumentNullException("command");
}
var result = new RequestStatus();
return result;
}
}
我在這個配置輔助角色使用Ninject:
_kernel.Bind(x => x.FromAssembliesMatching("Business.dll")
.SelectAllClasses()
.BindDefaultInterface());
該作品罰款和依賴正在被注入。
我有其使用JSON序列化並且這被放置在天青消息隊列QueuedCommand對象:
public class QueuedCommand
{
public string ClassName { get; set; }
public object Command { get; set; }
public DateTime AddedOn { get; set; }
public int AddedByUserId { get; set; }
public int RetryCount { get; set; }
}
這裏是(未優化)碼,其試圖deserialise的QueueCommand並對其進行處理:
var queuedCommand = (QueuedCommand)JsonConvert.DeserializeObject<QueuedCommand>(message.AsString);
var commandInterface = typeof(ICommand);
var commandType = (from assembly in AppDomain.CurrentDomain.GetAssemblies()
from type in assembly.GetTypes()
where (commandInterface.IsAssignableFrom(type)) && (commandInterface != type)
&& type.FullName == queuedCommand.ClassName
select type).FirstOrDefault();
var o = (JObject) queuedCommand.Command;
var command = (ICommand)o.ToObject(commandType);
var result = _commandDispatcher.Dispatch(command);
這一切工作正常,如果我調試,傳遞給調度員的命令對象是正確的類型,並填充預期值。
CommandDispatcher應該爲它給出的命令找到CommandHandler的具體實現。我的問題是,它不是,我收到一個關於ICommandHandler沒有綁定的錯誤。
如果我從ICommand中替換強制轉換爲SetZoneModeCommand,那麼它將按預期工作。這顯然是不可接受的,我認爲如果我有一個對象和一個完全合格的類名,就不會太難。
public interface ICommandDispatcher
{
/// <summary>
/// Dispatches a command to its handler
/// </summary>
/// <typeparam name="TParameter">Command Type</typeparam>
/// <param name="command">The command to be passed to the handler</param>
RequestStatus Dispatch<TParameter>(TParameter command) where TParameter : ICommand;
}
public CommandDispatcher(IKernel kernel)
{
if (kernel == null)
{
throw new ArgumentNullException("kernel");
}
_kernel = kernel;
}
public RequestStatus Dispatch<TParameter>(TParameter command) where TParameter : ICommand
{
var handler = _kernel.Get<ICommandHandler<TParameter>>();
return handler.Execute(command);
}
非常感謝您在百忙之中回覆時間。我知道我必須使用MakeGenericMethod,但不知道如何。我已經改變了我的代碼以符合你的建議,但是現在出現錯誤:「方法'CommandProcessor.GetMethod(Expression >)'的類型參數不能從使用推斷出來,請嘗試明確指定類型參數。 –
@JohnMc對不起,我已經按內存鍵入了大部分代碼。現在應該修正錯誤:'GetMethod(c => _commandDispatcher.Dispatch(c))''。希望沒有更多。 –
BatteryBackupUnit
尚未測試,但現在正在編譯。謝謝,如果可以的話,我會給你一百+ 1! –