我正在尝试这样做:
public interface IVirtualInterface{ }
public interface IFabricationInfo : IVirtualInterface
{
int Type { get; set; }
int Requirement { get; set; }
}
public interface ICoatingInfo : IVirtualInterface
{
int Type { get; set; }
int Requirement { get; set; }
}
public class FabInfo : IFabricationInfo
{
public int Requirement
{
get { return 1; }
set { }
}
public int Type
{
get {return 1;}
set{}
}
}
public class CoatInfo : ICoatingInfo
{
public int Type
{
get { return 1; }
set { }
}
public int Requirement
{
get { return 1; }
set { }
}
}
public class BusinessObj
{
public T VirtualInterface<T>() where T : IVirtualInterface
{
Type targetInterface = typeof(T);
if (targetInterface.IsAssignableFrom(typeof(IFabricationInfo)))
{
var oFI = new FabInfo();
return (T)oFI;
}
if (targetInterface.IsAssignableFrom(typeof(ICoatingInfo)))
{
var oCI = new CoatInfo();
return (T)oCI;
}
return default(T);
}
}
但是收到编译器错误:Canot将类型'GenericIntf.FabInfo'转换为T
我该如何解决这个问题?
感谢 苏尼特
答案 0 :(得分:4)
假设所有IVirtualInterface实现都有一个默认构造函数(如您的示例所示),您可以这样做:
public T VirtualInterface<T>() where T : IVirtualInterface, new()
{
return new T();
}
Simples!
修改强>
您要尝试实现的目标很难从您发布的代码中确定。为什么VirtualInterface不是静态的(暗示所有业务对象都继承了这个看似奇怪的方法)?如果您需要能够为IVirtualInterface实现参数化构造函数,那些参数值将来自哪里(您没有将任何参数传递给VirtualInterface方法)?
如果你只是想避免混乱intellisense(尝试像这样的恕我直言的一个不好的理由),但也希望保持对参数化构造函数的支持,那么这个怎么样:
public T VirtualInterface<T>(Func<T> constructor) where T : IVirtualInterface
{
return constructor();
}
使用方法:
IFabricationInfo fabInfo =
new BusinessObj().VirtualInterface<IFabricationInfo>(() => new FabInfo());
总的来说,如果没有足够的信息做出可靠的判断,我不得不说这是smells。
答案 1 :(得分:1)
T
和FabInfo
都实现IVirtualInterface
这一事实并不意味着您可以在两种类型之间执行转换。例如,如果T
为CoatInfo
,那么它与FabInfo
不兼容。
接口允许您根据它们提供的方法将不同对象视为相似类型。但是,这并不意味着您可以在这两种类型之间执行强制转换,因为它们的实际实现可能会有很大差异。
修改:再次重新阅读您的方法后,我发现您首先要检查类型。问题是编译器在尝试进行转换之前不知道您正在执行该逻辑。如果您正在编写通用方法并且正在检查T
的类型,那么您可能会滥用泛型的概念。请参阅其他答案,了解您应该如何创建T
的新实例。
答案 2 :(得分:0)
您可以在转换为T之前首先转换为object
来解决此错误。
return (T)(object)oFI;
,同样适用于CoatInfo
但是我认为切换泛型类型是一种滥用,因为如果你想要有限数量的可能返回值,你可以明确选择这些选项,例如。
public IFabricationInfo GetFabricationInfo()
{
return new FabInfo();
}