泛型方法调用,don';I don’我不想寄我的打字本
本文关键字:don 我不想 我的 打字本 调用 泛型方法 | 更新日期: 2023-09-27 18:26:05
我正在试验我的命令和一些通用方法。我没怎么用仿制药,所以现在我的大脑一团糟,希望能得到一些帮助。
我想要的是通过最后一个测试。然后返回我的TResult,而无需我在调用中提供TCommand和TResult。
invoker.Execute(command)
由于该命令实现
: CommandBase<TestResult>
我以为编译器会解决的。
但是编译器只带我去void方法。
非常感谢!
编辑:完整的代码位于:http://codepaste.net/7rjg2e
命令调用程序
public interface ICommandInvoker
{
void Execute<TCommand>(TCommand command) where TCommand : ICommand;
TResult Execute<TCommand, TResult>(TCommand command) where TCommand : ICommand<TResult>;
}
public class CommandInvoker : ICommandInvoker
{
...
public void Execute<TCommand>(TCommand command) where TCommand : ICommand
{
var handler = _container.GetInstance<ICommandHandler<TCommand>>();
handler.Handle(command);
_session.SaveChanges();
}
public TResult Execute<TCommand, TResult>(TCommand command) where TCommand : ICommand<TResult>
{
var handler = _container.GetInstance<ICommandHandler<TCommand>>();
handler.Handle(command);
return command.Result;
}
}
命令
public interface ICommand
{
bool IsValid { get; }
}
public interface ICommand<TResult> : ICommand
{
TResult Result { get; }
}
public class CommandBase : ICommand
{
public bool IsValid
{
get { return false; }
}
}
public class CommandBase<TResult> : ICommand<TResult>
{
public bool IsValid { get { return false; } }
public TResult Result { get; set; }
}
命令处理程序
public interface ICommandHandler<TCommand>
{
void Handle(TCommand command);
}
public interface ICommandHandlerWithResult<TCommand, TResult> where TCommand : ICommand<TResult>
{
void Handle(TCommand command);
}
测试类
public class TestCommandWithResult : CommandBase<TestResult>
{
public string Id { get; set; }
}
public class TestResult
{
public string Message { get; set; }
}
测试有效
[Test]
public void CanExcecuteWithResult()
{
var command = new TestCommandWithResult { Id = "billy" };
ObjectFactory.ResetDefaults();
var mockHandler = new Mock<ICommandHandler<TestCommandWithResult>>();
var sessionMock = new Mock<ISession>();
ObjectFactory.Configure(x => x.For<ICommandHandler<TestCommandWithResult>>().Use(mockHandler.Object));
var invoker = new CommandInvoker(ObjectFactory.Container, sessionMock.Object);
var result = invoker.Execute<TestCommandWithResult, TestResult>(command);
mockHandler.Verify(x => x.Handle(command));
}
我想通过的测试
[Test]
public void CanExcecuteWithResult()
{
var command = new TestCommandWithResult { Id = "billy" };
ObjectFactory.ResetDefaults();
var mockHandler = new Mock<ICommandHandler<TestCommandWithResult>>();
var sessionMock = new Mock<ISession>();
ObjectFactory.Configure(x => x.For<ICommandHandler<TestCommandWithResult>>().Use(mockHandler.Object));
var invoker = new CommandInvoker(ObjectFactory.Container, sessionMock.Object);
var result = invoker.Execute(command); // <-- this only calls void version
mockHandler.Verify(x => x.Handle(command));
}
这来自语言规范中的类型推理规则。
约束CCD_ 1在确定推断类型中不起作用。
因此,类型推理算法只使用
Execute<TComamnd, TResult>(TCommand command)
以推断CCD_ 2的类型。但是在参数CCD_ 3中没有用于确定类型CCD_。
因此,过载
TResult Execute<TCommand, TResult>(TCommand command)
不是适用的函数成员,因为它无法计算TResult
。
自7.5.2
如果特定方法的类型推理失败,则该方法不参与重载解析。
这里,TResult
的类型推断失败。
除非TResult作为参数传入,否则编译器无法计算出TResult是什么。它能够计算出TCommand的类型是什么,因为它是传入的
我看不出你需要TCommand的任何原因,你有一个足够好的接口,你唯一需要泛型的地方是在返回上。作为一个建议,尝试更改ICommandInvoker的签名,这将给你想要的:
public interface ICommandInvoker
{
void Execute(ICommand command);
TResult Execute<TResult>(ICommand<TResult> command);
}
编辑:
事实上,我确实明白你为什么想要TCommand,因为你在容器上使用泛型类型,但我的答案仍然有效。你能把类型而不是泛型传递给你的容器吗?
public TResult Execute<TResult>(ICommand<TResult> command)
{
Type commandHandlerType = typeof(ICommandHandler<>).MakeGenericType(command.GetType());
var handler = _container.GetInstance(commandHandlerType);
handler.Handle(command);
return command.Result;
}