简体   繁体   English

C#-创建一个其构造函数采用通用参数的类,导致转换异常

[英]C# - creating a class whose constructor takes generic param results in casting exception

I have IInfo and its generic version: 我有IInfo及其通用版本:

public interface IInfo
{
    IInput Input { get; }
}

public interface IInfo<T> : IInfo where T : IInput
{
    new T Input { get; }
}

Class implementation: 类的实现:

public class Info : IInfo<IInput>
{
    public IInput Input { get; }    

    public Info (IInput input) {}
}

Factory to create IOutput from IInput: 从IInput创建IOutput的工厂:

public class GenericFactory<TInput, TOutput> where TInput : IInput where TOutput : IOutput
{
    public IOutput Create(IInfo info)
    {
        ConstructorInfo cInfo = typeof(TOutput).GetConstructor(new[] { typeof(IInfo<TInput>) });
        object output = cInfo.Invoke(new object[] {cInfo});
    }
}

To test the above code: 要测试上面的代码:

public class TestInput : IInput 
{       
}

public abstract class AbstractOutput<TInput> : IOutput where TInput : IInput
{       
}

public class TestOutput: AbstractOutput<TestInput>
{
    public TestOutput(IInfo<TestInput> info)
    {

    }       
}

public void Test()
{
    IInput input = new TestInput();
    IInfo info = new Info(input);

    var factory = new GenericFactory<TestInput, TestOutput>();
    IOutput output = factory.Create(info);
}

I get the following error: 我收到以下错误:

Object of type 'Info' cannot be converted to type'Info<TestInput>'.

Side note: I'm open to any suggestions to simplify/re-write the code in a different way. 旁注:我愿意接受任何以不同方式简化/重写代码的建议。

public TestOutput(IInfo<TestInput> info)
{

}

Is expecting an IInfo<TestInput> explicitly . 明确期望IInfo<TestInput> However, you're trying to call it with IInfo<IInput> (which is what Info is designed to be). 但是,您尝试使用IInfo<IInput> (这是Info的设计目标)来调用它。

To make it clear, you could also write: 为了清楚起见,您还可以编写:

IInput input = new OtherInput();
IInfo info = new Info(input);

var factory = new GenericFactory<TestInput, TestOutput>();
IOutput output = factory.Create(info);

And now you've provided IInfo<OtherInput> to something expecting IInfo<TestInput> 现在您提供IInfo<OtherInput>的东西期待IInfo<TestInput>

You would need to make IInfo<T> contravariant to allow it to be cast, for example: 您需要做IInfo<T> 逆变允许它定投,例如:

public interface IInfo<in T> : IInfo 
    where T : IInput
{
    //new T Input { get; }
}

But note that it's illegal to return T when with a contravariant interface. 但是请注意,使用逆接口时返回T是非法的。 The alternative is to make Info generic, and change Create to accept IInfo<TInput> . 另一种方法是使Info通用,并更改Create以接受IInfo<TInput> That latter gives you the benefit of a compile-time error when trying to pass IInfo<OtherInput> to Create() , rather than a run-time error 当尝试将IInfo<OtherInput>传递给Create() ,后者会给您带来编译时错误的好处,而不是运行时错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM