假设我们有一个非通用的基接口,带有一个通用的继承接口:
public interface IFoo { }
public interface IBar<T, K> : IFoo {
K Do(T t);
}
public class BarImpl : IBar<Type, AnotherType> {
public AnotherType Do(Type type) {
return new AnotherType(type);
}
}
我需要创建一个返回IFoo实例的工厂,但是使用返回的实例我需要能够调用派生类型Do(T),这是不可用的。
public class FooFactory() {
IFoo Get() {
// simplified, in reality i am returning the correct
// type by checking the generic interface
// types to get an object from a stored list
// of implementations
return BarImpl();
}
}
// Now in another class
public void DoFoo() {
IFoo iFoo = new FooFactory().Get();
// Need to be able to call iFoo.Do(Type) but cannot
}
我能够让它工作的唯一方法是创建一个动态对象,而不是IFoo,然后调用Do() - 这在我的情况下有效,但我失去了一些类型安全,我更喜欢保持。
我的问题是我可以重新设计它以便能够访问派生接口方法,同时仍然能够维护IFoo的列表(以及随后的工厂方法返回类型)
答案 0 :(得分:3)
您期望或希望类型安全,但请以这种方式考虑:
Do
,Get
需要返回定义该方法的类型。 IFoo
没有它,但IBar<T, K>
却有。 Get
会返回一个IFoo
对象,但不保证是IBar<T, K>
。Get
的实现确保只返回IBar<T, K>
,类型系统也无法知道此而不实际返回该类型。 Do
方法的类型,则类型将不清楚:您需要将类型T
的对象传递给它。但是,返回的IFoo
或IBar<T, K>
不一定使用您要传递给T
的相同类型Do
。Get
的实施会提供此功能(例如“让我IBar<T, K>
接受类型T
”),类型系统也有办法反映这一点,那么这仍然不会说K
。对于已知的T
,它可能仍然是IBar<T, int>
或IBar<T, string>
。如果没有实际的具体类型,实际上没有办法知道。Do
的返回类型说些什么。我的观点是,当您确实有理由维护具体类型时,您只需要泛型类型。通常,如果从另一个非泛型方法调用泛型方法或泛型类型的方法,那么您要么使用一组离散的类型,要么实际上不需要泛型类型信息。
所以也许你最好在这里引入非通用IBar
类型:
interface IBar
{
object Do(object t);
}
interface IBar<T, K> : IBar
{
K Do(T t);
}
public class BarImpl : IBar<Type, AnotherType>
{
public AnotherType Do(Type type)
{
return new AnotherType(type);
}
public object Do(object t)
{
return Do((Type) t);
}
}
然后,您可以让Get
返回IBar
,然后您可以拨打Do
。
顺便说一下。这种模式在BCL中非常常用,例如: IEnumerable<T>
和IEnumerable
。
答案 1 :(得分:0)
您可以向object DoIt()
添加IFoo
方法,然后BarImpl
将实施该方法:
public object DoIt()
{
return Do(typeof(T));
}
这里的问题是你需要将DoIt
的返回值转换为实际类型。但是你不会知道先前是什么。