在 C# 依赖注入中使用具有不同约束的实现时出错

问题描述 投票:0回答:1

我正在努力让这样的代码工作

e
实例没问题,有
Foo1
Foo2

但是当尝试构建

c
的实例和
d
的实例时,它会抛出 TypeLoadException。

它应该在两个类中构建它

Foo1
没有任何问题,其中一个包含在
IEnumerable
中,不是吗?

或者我应该在添加到

ServiceCollection
时写选择机制吗?

internal class Program
{
    private static void Main(string[] args)
    {
        var sc = new ServiceCollection();
        sc.AddSingleton(typeof(IFoo<>), typeof(Foo1<>));
        sc.AddSingleton(typeof(IFoo<>), typeof(Foo2<>));
        sc.AddSingleton<C>();
        sc.AddSingleton<D>();
        sc.AddSingleton<E>();

        var sp = sc.BuildServiceProvider();

        var e = sp.GetRequiredService<E>();
        var c = sp.GetRequiredService<C>();
        var d = sp.GetRequiredService<D>();
        
    }
}

public class C
{
    public IFoo<Bar>[] Foos { get; }

    public C(IEnumerable<IFoo<Bar>> foos)
    {
        Foos = foos.ToArray();
    }
}

public class D
{
    public IFoo<Bar> Foo { get; }

    public D(IFoo<Bar> foo)
    {
        Foo = foo;
    }
}

public class E
{
    public IFoo<BarEq>[] Foos { get; }

    public E(IEnumerable<IFoo<BarEq>> foos)
    {
        Foos = foos.ToArray();
    }
}

public class Bar(int I);

public record BarEq(int I);

public interface IFoo<T> { }

public sealed class Foo1<T> : IFoo<T> { }

public sealed class Foo2<T> : IFoo<T> where T : IEquatable<T> { }

我得到的例外是

System.TypeLoadException: 'GenericArguments[0], 'Bar', on 'Foo2`1[T]' 违反了类型参数 'T' 的约束。

堆栈跟踪

en System.RuntimeTypeHandle.Instantiate(RuntimeType inst) en /_/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs: línea 540
en System.RuntimeType.MakeGenericType(Type[] instantiation) en /_/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs: línea 3522

.csproj 文件

<Project Sdk="Microsoft.NET.Sdk">

    <PropertyGroup>
        <OutputType>WinExe</OutputType>
        <TargetFramework>net8.0</TargetFramework>
        <ImplicitUsings>enable</ImplicitUsings>
        <Nullable>enable</Nullable>
        <AssemblyVersion>1.0</AssemblyVersion>
        <FileVersion>1.0.23.0</FileVersion>
    </PropertyGroup>

    <ItemGroup>
      <PackageReference Include="Microsoft.Extensions.Logging" Version="8.0.0" />
      <PackageReference Include="Serilog.Extensions.Logging.File" Version="3.0.0" />
    </ItemGroup>

</Project>
c# asp.net-core dependency-injection .net-8.0
1个回答
0
投票

您可能看到的是“首次更改异常”。发生这种情况是因为内置 DI 容器的限制。 它尝试找出是否可以基于

Foo2<T>

抽象创建

IFoo<Bar>
,并通过尝试调用
typeof(Foo2<>).MakeGenericType(typeof(Bar))
来实现这一点。当该调用失败时(确实如此),DI 容器会跳过
Foo2<T>
的创建,将其作为集合的一部分。
对此你无能为力,并且可以忽略这个第一次机会异常;您的应用程序将继续运行。

© www.soinside.com 2019 - 2024. All rights reserved.