简体   繁体   English

如何将泛型类型的抽象类约束到派生类的接口?

[英]How to constrain generic type of abstract class to interface of derived class?

My question is similar to this question with the difference that rather than constraining to to the derived class directly I would like to constrain to the interface on that class. 我的问题类似于这个问题 ,区别在于我不想直接约束到派生类,而是想限制该类的接口。

Some background: I am trying to create a type safe interface driven framework for creating SignalR Hub Proxies, mainly for the case that if a hub name or one of its methods change I don't have to search through a bunch of strings to resolve the issue; 一些背景:我正在尝试创建一个类型安全的接口驱动框架来创建SignalR Hub代理,主要是因为如果一个集线器名称或其中一个方法改变我不必搜索一堆字符串来解决问题; on that note my signal r client is all dot net so no worries about java script. 在那个笔记上我的信号r客户端都是点网,所以不用担心java脚本。

So if I have this base class: 所以,如果我有这个基类:

public abstract class BaseClientProxy<T>
{
    protected IHubProxy proxy;

    protected void Invoke<TDto>(TDto dto)
    {
        proxy.Invoke(this.GetCallingMethod(), dto);
    }

    protected void Invoke()
    {
        proxy.Invoke(this.GetCallingtMethod());
    }

    protected BaseClientProxy(HubConnection conn)
    {
        proxy = conn.CreateHubProxy<T>();
    }
}

And a hub proxy like: 和集线器代理如:

    public class FoobarServiceProxy : BaseClientProxy<IFoobarService>, IFoobarService
{
    public FoobarServiceProxy(HubConnection conn) : base(conn)
    {          
    }

    public void Bar(BarDto bar)
    {
        proxy.Invoke(this.GetCurrentMethod(), bar);
    }

    ...
}

How could I Remove the need to Specify the interface to both the base and the derived? 我怎么能不需要指定基础和派生的接口? I am open to restructuring this a bit as well as I'm not too far down the proverbial rabbit hole yet. 我对这一点进行重组是开放的,而且我还没有离开那个众所周知的兔子洞。

It appears that what you want is a sort of "generic proxy", which you can create against any interface. 看来你想要的是一种“通用代理”,你可以针对任何界面创建它。 You want to do something like this: 你想做这样的事情:

public abstract class BaseClientProxy<T> : T

In other words, you want to have a class implement an interface that is not known at compile time. 换句话说,您希望让类实现一个在编译时未知的接口。

That is not allowed. 这是不允许的。 If you try to compile it, you get 如果你试图编译它,你得到

error CS0689: Cannot derive from 'T' because it is a type parameter

That is impossible to compile since you have no idea what the members of T are going to be. 这是不可能编译的,因为你不知道T的成员会是什么。 Even if you placed a type constraint on T that would allow the compiler to know some of its members, you still could not know all of the members that may needed at run time (for, eg child interfaces that add members). 即使你在T上放置了一个允许编译器知道其某些成员的类型约束,你仍然无法知道运行时可能需要的所有成员(例如,添加成员的子接口)。

However, you can add a type constraint to the abstract class that will guarantee that T implements a given interface in all cases. 但是,您可以向抽象类添加类型约束,以确保T在所有情况下都实现给定的接口。 Unfortunately, you still have to apply the same constraint on all subclasses, but fortunately the compiler checks that for you. 不幸的是,您仍然必须对所有子类应用相同的约束,但幸运的是编译器会为您检查。

Another alternative would be to make the proxy a member of the parent class (instead of a base): 另一种方法是使代理成为父类的成员 (而不是基类):

public abstract BaseClientProxy<T>
{
    public T Client {
        // etc
    }
}

You couldn't substitute the proxy itself for T 's, but you would be unconstrained in your choice of T . 你无法用代理本身代替T ,但你在选择T不会受到限制。 This might be acceptable if you can tell in client usage whether or not you have a proxy (which may defeat the purpose). 如果你能告诉客户使用你是否有代理(这可能会破坏目的),这可能是可以接受的。 If, as you say, you are still in the design phase, maybe you could instead adjust clients to match this structure. 如果,正如您所说,您仍处于设计阶段,也许您可​​以调整客户端以匹配此结构。

If I understand correct, you want something like 如果我理解正确,你需要类似的东西

public abstract class BaseClient<T> : T
{ ... }

This is not possible in .NET. 这在.NET中是不可能的。 Even if that was possible, at that level T does not offer any information (in any case it is guaranteed to be Object, an interface that you already have). 即使这是可能的,在那个级别T不提供任何信息(在任何情况下它都保证是Object,一个你已经拥有的接口)。 If you restrict T to an interface then it would be odd. 如果将T限制为接口,则会很奇怪。 You can restrict any derived class to implement any interface you want by saying you implement them and leave all interface operations as abstract (in other words you already have this constraint). 您可以通过声明实现它们来限制任何派生类来实现您想要的任何接口,并将所有接口操作保留为抽象(换句话说,您已经具有此约束)。

If you want to derive from BaseClient a GeneralFoo where T is a concrete interface but its implementations can vary, then I would go for aggregate. 如果你想从BaseClient派生一个GeneralFoo,其中T是一个具体的接口,但它的实现可以变化,那么我会去聚合。 Simply add a property of type T to BaseClient and if any derived class will want to restrict T can do so and use that property. 只需将类型为T的属性添加到BaseClient,如果任何派生类想要限制,T可以这样做并使用该属性。 The returned instance is guaranteed to implement the interface you constraint T to. 保证返回的实例实现约束T的接口。

Hope it helps 希望能帮助到你

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 将方法上的泛型类型约束为从抽象泛型基类的任何变体形式派生的任何类 - Constrain generic type on a method to be any class that is derived from any variant form of an abstract generic base class 检查类型是否派生自抽象泛型类 - Check if type is derived from abstract generic class 如何使用Singleton将派生类型传递给抽象类 - How to pass derived type to abstract class with singleton 如何将通用集合约束到 class 名称和接口 - How to constrain a generic collection to both a class name and an interface 是一个抽象类的一种接口? - is an abstract class a type of interface? 为什么派生类不能使用扩展该接口的类型覆盖基类的接口类型抽象属性? - Why can't a derived class override base class' interface type abstract property with a type that extends that interface? 如何将泛型类型限制为 class 并支持 new()? - How do you constrain a generic type to be a class and support new()? 派生类型的通用基类 - Derived type of generic base class 无法将 C# 基类构造函数约束为仅接受使用派生类型作为泛型类型的类型的注入对象 - Cannot constrain C# base class constructor to only accept injected object of a type that uses the derived type as generic type 如何确保派生自抽象泛型 class 的 class 使用自身作为泛型参数 - How to ensure that class derived from abstract generic class uses itself as generic parameter
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM