2017-08-07 64 views
1

我有以下的实施产生一个编译器错误通用工厂方法创建泛型类型来龙去脉

“无法隐式转换类型‘ParentMenuItemFilter’到 ‘IMenuItemFilter<MenuItem>’。一个显式转换存在(是你 缺少强制转换?)

public class MenuItem 
{ 
    // implementation removed for clarity 
} 

public class ParentMenuItem : MenuItem 
{ 
    // implementation removed for clarity 
} 

public interface IMenuItemFilter<TMenuItemType> 
     where TMenuItemType : MenuItem 
{ 
    TMenuItemType ApplySecurity(TMenuItemType menuItem); 
} 


public class ParentMenuItemFilter : IMenuItemFilter<ParentMenuItem> 
{ 
    public ParentMenuItem ApplySecurity(ParentMenuItem menuItem) 
    { 
     // implementation removed for clarity 
    } 
} 

public class MenuItemFilterFactory 
{ 
    public IMenuItemFilter<MenuItem> Create<TMenuItemType>(TMenuItemType menuItem) 
      where TMenuItemType : MenuItem 
    { 
     if (typeof(TMenuItemType) == typeof(ParentMenuItem)) 
     { 
      // here is the errored line!... 
      return new ParentMenuItemFilter(this); 
     } 
     else if (/* create some other types*/) 
     { 
      ... 
     } 
    } 
} 

所以我的两个最好的朋友,协方差和逆变进来玩。我想实现上述,如果它是可能是通过通用工厂方法,它将返回IMenuItemFilter的相应实例,该实例将根据menuItem参数对Create方法起作用。

我想将MenuItem实例传递给工厂方法以解决此问题。

我试过在界面和其他定义中有一个进出in TMenuItemTypeIn, out TMenuItemTypeOut - 无济于事。我曾在Stack Exchange的CodeReview上发布过50/50,但认为这同样是一个编码问题和代码设计问题。今天我花了很大一部分时间试图让这个工作,但有很多中断。

+0

我想你需要的只是'公共接口IMenuItemFilter '。但是,如果你检查实际的类型,这是非常不通用的,不是吗?我怀疑你的方案需要泛型,或者至少不适合你的工厂。 – HimBromBeere

+0

因为IMenuItemFilter指定了与in和out参数相同的TMenuItemType,所以我不能这样做吗?在这个编译器barfs! – Andez

+0

是否有你没有从你的工厂方法返回'IMenuItemFilter '的原因? –

回答

2

如果这不是一个过于简单化的例子,那么每个类型都应该有一个方法。 CreateParentMenuItemFilter或类似的东西。你的通用方法似乎只会使事情复杂化,没有任何好处。

+0

事实上,裂缝正在出现。我正在寻找一个优雅的方法 - 只是重新思考整体问题的代码策略。 – Andez

1

我想你所需要的只是public interface IMenuItemFilter<out TMenuItemType>。然而,基于泛型类型参数完成不同事情的泛型方法有点奇怪,而不是泛型的意图 - 这就是为什么它们被称为泛型:它们对不同的类执行相同的操作。

所以我建议去非通用在你的工厂:

public class MenuItemFilterFactory 
{ 
    public IMenuItemFilter Create(MenuItem menuItem) 
    { 
     if (menuItem.GetType() == typeof(ParentMenuItem)) 
     { 
      return new ParentMenuItemFilter(this); 
     } 
     else if (/* create some other types*/) 
     { 
      ... 
     } 
    } 
} 

但是这里假设你有你的界面的非通用版本,以及从通用的一个派生:

public interface IMenuItemFilter 
{ 
} 
public interface IMenuItemFilter<TMenuItemType> : IMenuItemFilter 
     where TMenuItemType : MenuItem 
{ 
    TMenuItemType ApplySecurity(TMenuItemType menuItem); 
} 
+0

但是,如果我从工厂返回'IMenuItemFilter',我无法访问位于'IMenuItemFilter '上的'ApplySecurity'方法' – Andez