来自泛型方法的派生接口

时间:2010-05-18 20:48:03

标签: c#

我正在尝试这样做:

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

我该如何解决这个问题?

感谢 苏尼特

3 个答案:

答案 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)

TFabInfo都实现IVirtualInterface这一事实并不意味着您可以在两种类型之间执行转换。例如,如果TCoatInfo,那么它与FabInfo不兼容。

接口允许您根据它们提供的方法将不同对象视为相似类型。但是,这并不意味着您可以在这两种类型之间执行强制转换,因为它们的实际实现可能会有很大差异。

修改:再次重新阅读您的方法后,我发现您首先要检查类型。问题是编译器在尝试进行转换之前不知道您正在执行该逻辑。如果您正在编写通用方法并且正在检查T的类型,那么您可能会滥用泛型的概念。请参阅其他答案,了解您应该如何创建T的新实例。

答案 2 :(得分:0)

您可以在转换为T之前首先转换为object来解决此错误。

return (T)(object)oFI;

,同样适用于CoatInfo

但是我认为切换泛型类型是一种滥用,因为如果你想要有限数量的可能返回值,你可以明确选择这些选项,例如。

public IFabricationInfo GetFabricationInfo()
{
    return new FabInfo();
}