2017-08-25 64 views
0

我有一种情况,我想根据作为参数传入的接口的实现来创建类的实例。理解返回具有通用参数的派生类作为基接口

public interface IFooParameters 
{ 
    int Id { get; } 
} 

public interface IFooParametersAdditional 
{ 
    int AnotherProperty { get; } 
} 

public class FooBarParameters : IFooParameters 
{ 
    public int Id { get; set; } = 1; 
    public int Bar { get; set; } = 42; 
} 

public class FooBazParameters : FooBarParameters, IFooParametersAdditional 
{ 
    public int Baz { get; set; } = 55; 
    public int AnotherProperty { get; set; } = 99; 
} 

public interface IFoo<in TFooParameters> 
    where TFooParameters : IFooParameters 
{ 
    void DoStuff(TFooParameters parameters); 
} 

public class Bar : IFoo<FooBarParameters> 
{ 
    public void DoStuff(FooBarParameters parameters) 
    { 
     throw new System.NotImplementedException(); 
    } 
} 

public class Baz : IFoo<FooBazParameters> 
{ 
    public void DoStuff(FooBazParameters parameters) 
    { 
     throw new System.NotImplementedException(); 
    } 
} 

public class Another : IFoo<FooBazParameters> 
{ 
    public void DoStuff(FooBazParameters parameters) 
    { 
     throw new System.NotImplementedException(); 
    } 
} 

public interface IFooFactory 
{ 
    IFoo<IFooParameters> GetInstance(IFooParameters parameters); 
} 

public class FooFactory : IFooFactory 
{ 
    public IFoo<IFooParameters> GetInstance(IFooParameters parameters) 
    { 
     if (parameters.Id == 1) 
      return new Bar(); // *** compiler error 

     if (parameters.Id == 2) 
      return new Baz(); // *** compiler error 

     return new Another(); // *** compiler error 
    } 
} 

// *** compiler error是:

错误CS0266无法隐式转换类型'Bar''IFoo<IFooParameters>'。一个显式转换存在(是否缺少强制转换?)

我不知道为什么我得到这个,因为我认为衍生实现应该(我还以为)隐式转换到他们的基地为Bar : IFoo<FooBarParameters>,和FooBarParameters : IFooParameters这个工作(以仿制药没带):

public interface IBar { } 
public class BarBar : IBar { } 

public class Test 
{ 
    public IBar Thing() 
    { 
     return new BarBar(); 
    } 
} 

背后就是我希望做到的是,也有根据类型的IFooParameters两种可能实现通入FooFactory,基本思想和一些验证,返回的实例- 我只关心返回接口,因为IFoo<IFooParameters的所有实现之间的基础API是相同的,尽管一个实现需要通过FooBazParameters的附加属性。

我对泛型非常陌生,所以我不确定我试图做的是完全错误的,还是只是在实现中丢失了某些东西。但是,对于正在发生的事情的任何帮助和/或解释是值得赞赏的。

小提琴: https://dotnetfiddle.net/wjyLS7

与投轻微改变: https://dotnetfiddle.net/ZFQjCn

+1

我在编译第一个代码块时没有遇到错误。你需要发布一个适当的repro。 –

+0

@MthetheWWatson只要复制粘贴代码,就会给我同样的错误,就像我期望的那样,给定代码(它不可能被允许编译)。 – Servy

+0

@MatthewWatson是啊我不知道你是如何获得一个成功的构建,即使我附加的第一个小提琴有一个编译器错误。 – Kritner

回答

3

如果编译器允许你一个Bar实例转换为IFoo<IFooParameters>那么你就可以调用该DoStuff返回的值传递一个FooBazParameters实例作为参数,但Bar实例仅允许接受FooBarParameters实例。阻止您以无效方式使用Bar实例的唯一方法是阻止该转换生效。

+0

啊,这很有道理!有什么办法可以完成我想要做的事情吗? (有助于放弃工厂,只是让客户端直接推出'IFoo <...>'') – Kritner

+1

@Kritner鉴于您对接口的不同实现进行不同处理对于您来说绝对没有任何意义,因此它甚至没有意义你首先要有一个接口(或者你应该重新设计你的程序,以便你可以*交换接口的实例)。 – Servy

+0

是啊,似乎必须成为我的路线。至少我现在明白***为什么***不起作用。谢谢! – Kritner