首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >通用接口,泛型接口与泛型接口

通用接口,泛型接口与泛型接口
EN

Stack Overflow用户
提问于 2015-05-25 16:07:53
回答 2查看 176关注 0票数 1

很多人在我的问题中,我希望这仍然可以理解.

我有以下接口:

代码语言:javascript
复制
public interface ICommandBus
{
    TResult Publish<TCommand, TResult>(TCommand command)
        where TResult : ICommandResult
        where TCommand : ICommand<TResult>;
}

public interface ICommand<T>
    where T : ICommandResult
{ }

public interface ICommandResult
{
    bool Success { get; }
}

我想以这种方式使用它们的实现(我省略了CommandBus,这对这个问题没有用,但您可以找到它这里):

代码语言:javascript
复制
public class CreateItemCommand: ICommand<CreateItemResult>
{
    public string Name { get; private set; }
}
public class CreateItemResult: ICommandResult
{
    public bool Success { get; private set; }
}

var command = new CreateItemCommand();
var result = commandBus.Publish(command); //Error here

我有一个错误:The type arguments cannot be inferred from the usage。我尝试了一些在……里面输出修饰符,但没有成功.

我如何调用我的Publish方法,使用它指定参数类型如下:

代码语言:javascript
复制
var result = commandBus.Publish<CreateItemCommand, CreateItemResult>(command); //Works, but ugly...

编辑:卢卡斯答案的更新

Lucas解决方案应该可以工作,但我仍然必须使用where TResult : ICommandResult约束来避免错误There is no boxing conversion or type parameter conversion from 'TResult' to 'Core.Command.ICommandResult'

我在继承方面也有一个很大的问题,假设我有以下抽象的CommandObserver:

代码语言:javascript
复制
public abstract class NotificationObserver<TResult> : ICommandObserver<TResult>
    where TResult : ICommandResult
{
    protected virtual bool IsEnable(ICommand<TResult> command, TResult result)
    {
        return true;
    }
}

它的实现

代码语言:javascript
复制
public class CreateItemObserver : NotificationObserver<CreateItemResult>
{
    protected override bool IsEnable(CreateItemCommand command, CreateItemResult result)
    {
        return !String.IsNullOrEmpty(command.Name);
    }
}

这是行不通的,因为实现并不真正覆盖虚拟方法(不是相同的签名:ICommand<TResult> != CreateItemCommand)。

如果我确实保留了正确的签名,那么在实现中如果没有丑陋的强制转换,我就不能使用CreateItemCommand属性.

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-05-26 08:30:27

我在这里看到仿制药过量使用;)太多的仿制药,简单的继承会给你带来更容易的结果。

如果您想在不完全重构的情况下使用类来消除太多的泛型:您只需要指定泛型函数调用,因为编译器没有足够的智能为您解决这个问题(自动解析泛型参数很好,解析泛型参数的泛型参数就不需要)。

代码语言:javascript
复制
var result = commandBus.Publish<CreateItemCommand, CreateItemResult>(command); 

它很重,并不特别优雅,但至少它能工作。另外,您的接口声明本身很重,所以使用起来也不奇怪。

票数 1
EN

Stack Overflow用户

发布于 2015-05-25 16:27:51

您可以像这样轻松地重写您的接口,以去掉TCommand参数:

代码语言:javascript
复制
public interface ICommandBus
{
    TResult Publish<TResult>(ICommand<TResult> command)
        where TResult : ICommandResult;
}

请注意,您还可以删除where TResult : ICommandResult,因为此约束与ICommand<TResult>中的定义是冗余的。

代码语言:javascript
复制
public interface ICommandBus
{
    TResult Publish<TResult>(ICommand<TResult> command);
}

我想C#拒绝推断在您的情况下的类型参数的原因是TCommand可以多次实现ICommand<T>,如下所示:

代码语言:javascript
复制
public class SomeCommand : ICommand<Foo>, ICommand<Bar>
{
    // ...
}
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30442141

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档