具有类型约束的部分通用接口

Partial generic interface with type constraint

我需要创建两个部分界面。一个有约束,一个没有约束,比如:

public partial interface IMyCuteInterface<T> where T : IEnumerable
{
    void DoSomethingOnlyPossibleIfGenericIsIEnumerable();
}

public partial interface IMyCuteInterface<T>
{
    void DoSomeStuff();
    void DoSomeStuff2();
}

这是实现:

public class CuteInterfaceImplementation<T> : IMyCuteInterface<T>
{
    private readonly T _element;
    public CuteInterfaceImplementation(T element)
    {
        _element = element;
    }

    public void DoSomethingOnlyPossibleIfGenericIsIEnumerable(){}
    public void DoSomeStuff(){}
    public void DoSomeStuff2() { }
}

这是一个更动态地获取它的静态方法:

public class CuteInterfaceImplementationBase
{
    public static IMyCuteInterface<T> From<T>(T t)
    {
        return new CuteInterfaceImplementation<T>(t);
    }
}

我想这样称呼它:

public static void Main(string[] args)
{
    var mci = CuteInterfaceImplementationBase.From(args);
}

因此,C# 要我将我在第一个接口中添加的泛型类型约束添加到我的 CuteInterfaceImplementationBase.From<T> 和我的 CuteInterfaceImplementation<T>-class.

我想要实现的是:args可以是例如来自类型 List<T> 或来自类型 int 或其他类型。我的目标是,如果 args 来自类型 IEnumerable<T> 我想向 CuteInterfaceImplementation-instance.

添加更多函数(通过带有约束的接口)

示例:

如果 args 来自 IEnumerable 类型,这个来自 CuteInterfaceImplementation 的实例有方法:

如果 args 来自 Fooint 类型(或任何未实现 IEnumerable 的类型),我可以使用方法:

表示DoSomethingOnlyPossibleIfGenericIsIEnumerable不可用。

但似乎这是不可能的,因为我需要将约束添加到我实现的 class。知道怎么做吗?

不确定这种方法是不是好主意,它违反了 SOLID 中的 "I" - 接口 隔离

no client should be forced to depend on methods it does not use

您正在使用 partial 拆分两个根本不同的界面,您应该有 2 个不同的界面,因为它们是不同的。

回答你的问题: 如果您致力于在 T 的条件下采用类似的方法,您可以拆分接口,将 "common logic"(两个接口都使用)移动到基础 class 并使用 From<T> 方法有条件地选择要创建的实现。

像这样:

public partial interface IMyCuteInterface_WITHEnumerable<T> : IMyCuteInterface<T> where T : IEnumerable
{
    void DoSomethingOnlyPossibleIfGenericIsIEnumerable();
}

public partial interface IMyCuteInterface<T>
{
    void DoSomeStuff();
    void DoSomeStuff2();
}

然后是实现:

public class CuteInterfaceImplementation<T> : CuteInterfaceImplementation_COMMON<T>
{
    public CuteInterfaceImplementation(T element) : base(element)
    {

    }
}

public class CuteInterfaceImplementation_COMMON<T> : IMyCuteInterface<T>
{
    private readonly T _element;
    public CuteInterfaceImplementation_COMMON(T element)
    {
        _element = element;
    }
    public void DoSomeStuff() { }
    public void DoSomeStuff2() { }
}

public class CuteInterfaceImplementation_WITHEnumerable<T> : CuteInterfaceImplementation_COMMON<T>,  IMyCuteInterface_WITHEnumerable<T> where T : IEnumerable
{
    private readonly T _element;
    public CuteInterfaceImplementation_WITHEnumerable(T element) : base(element)
    {
        _element = element;
    }

    public void DoSomethingOnlyPossibleIfGenericIsIEnumerable() { }
}

最后是 "static helper",它决定 class 实例化: 不幸的是,在 C# 中不可能有条件地实例化不同的 classes,因为一个人期望 TIEnumerable 而另一个人则没有。您可以使用 dynamic

来解决这个问题
public class CuteInterfaceImplementation_HELPER
{
    public static IMyCuteInterface<T> From<T>(T t)
    {
        if (t is IEnumerable)
        {
            dynamic dyn = t;
            return FromEnumerable(dyn);
        }
        else
        {
            return new CuteInterfaceImplementation<T>(t);
        }
    }

    public static IMyCuteInterface<T> FromEnumerable<T>(T t) where T: IEnumerable
    {
        return new CuteInterfaceImplementation_WITHEnumerable<T>(t);
    }
}