具有类型约束的部分通用接口
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
的实例有方法:
void DoSomethingOnlyPossibleIfGenericIsIEnumerable();
void DoSomeStuff();
void DoSomeStuff2();
如果 args 来自 Foo
或 int
类型(或任何未实现 IEnumerable
的类型),我可以使用方法:
void DoSomeStuff();
void DoSomeStuff2();
表示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,因为一个人期望 T
为 IEnumerable
而另一个人则没有。您可以使用 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);
}
}
我需要创建两个部分界面。一个有约束,一个没有约束,比如:
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
的实例有方法:
void DoSomethingOnlyPossibleIfGenericIsIEnumerable();
void DoSomeStuff();
void DoSomeStuff2();
如果 args 来自 Foo
或 int
类型(或任何未实现 IEnumerable
的类型),我可以使用方法:
void DoSomeStuff();
void DoSomeStuff2();
表示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,因为一个人期望 T
为 IEnumerable
而另一个人则没有。您可以使用 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);
}
}