0

给定以下接口:

public interface IContext {
    TOutput get<TInput, TOutput>(TInput command);
}

以及以下实现:

public class DbContext: IContext {}

public class Repository {
    private readonly IContext _context;

    public Repository(IContext context) {...}

    public IDto get(int id) {
        var data = _context.get<IThis, IThat>(id)
        //map data to dto and return
    }
}

由于我将IContext依赖项传递到Repository类中,因此我不希望接口上有类型参数,因为它会锁定我使用 IContext 的显式实现。有点静音接口的点对吗?

鉴于我在接口上没有类型参数的限制,我该IContext如何实现IContext以便我可以_context.get(...)在我的Repository类中调用而不是_context.get<IThis, IThat>(...)

所以换句话说,我希望IContext(在这个例子DBContext中)的实现来定义类型参数,get()这样当方法被实际调用时,调用者不需要知道任何关于要传递的类型参数的信息。

更新

我要解决的问题是允许将任何类型的内容IContext传递到存储库中。如果我在接口上有类级别的类型参数,那么我仅限于 的实现IContext<TThis, TThat>,这并不理想。

4

2 回答 2

1

如果IContext对象具有get可以接受任何对象作为输入并提供任何对象作为输出的函数很重要,那么您的接口方法应该简单地使用object

public interface IContext {
    object get(object command);
}

(接口的实现者可能会暴露一个强类型的方法,并为该方法使用显式接口实现。

另一种可能性是您的IContext对象在接受IContext对象时知道该方法的签名应该是什么。在这种情况下,您希望将接口而不是其方法设为通用:

public interface IContext<TInput, TOutput> {
    TOutput get(TInput command);
}

这当然意味着你不能拥有各种不同类型的IContext对象的集合。他们都需要共享一个签名。接受或返回IContext对象的方法需要在编译时知道输入/输出应该是什么类型,或者它们本身需要是通用的。

在可能与您使用接口相关或不相关的旁注中,您可以利用泛型参数的协变和逆变,这可能会或可能不会帮助您使用接口:

public interface IContext<in TInput, out TOutput>
{
    TOutput get(TInput command);
}

如果不了解您期望如何实际使用该界面,则不清楚哪个是更好的解决方案。

于 2013-10-17T19:47:41.670 回答
0

据我了解,您需要具体类型以及通过接口的松散耦合。考虑一下:

public interface ICommand {}

public interface IContextOutput {}

public interface IContext
{
    IContextOutput Get(ICommand input);
}

public abstract class ContextBase<TInput, TOutput> : IContext       
    where TInput : ICommand
    where TOutput : IContextOutput
{
    IContextOutput IContext.Get (ICommand input)
    {
        if (input.GetType () != typeof(TInput))
        {
            throw new ArgumentOutOfRangeException("input");
        }

        return Get((TInput)input);
    }

    protected abstract TOutput Get(TInput command);     
}

然后从抽象类派生所有上下文。

于 2013-10-17T20:20:05.233 回答