我有一种情况,我想创建一个类的实例,具体取决于作为参数传入的接口的实现。
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
,具体取决于类型和一些验证,返回{的实例{1}} - 我只关心返回接口,因为IFoo<IFooParameter>
的所有实现之间的底层API是相同的,尽管一个实现需要通过IFoo<IFooParameters
添加一个属性。
我对仿制药很陌生,所以我不确定我尝试做的事情是完全错误的,还是我在实现中遗漏了一些东西。但是对于正在发生的事情的任何帮助和/或解释都表示赞赏。
小提琴: https://dotnetfiddle.net/wjyLS7
使用演员略有变化: https://dotnetfiddle.net/ZFQjCn
答案 0 :(得分:3)
如果编译器允许您将std::map
实例转换为Bar
,那么您将能够在IFoo<IFooParameters>
实例中传递的返回值上调用DoStuff
作为参数,但FooBazParameters
实例仅允许接收Bar
个实例。阻止您以无效方式使用FooBarParameters
实例的唯一方法是阻止转换生效。