无法在通用 Class 激活器上找到构造函数
Can't Find Constructor on Generic Class Activator
我正在尝试为此 class 创建一个 AutoFixture.ISpecimenBuilder
:
public class DiscosObjectRelationship<T> where T : DiscosModelBase
{
private readonly string _linkAddress;
private readonly IDiscosClient _client;
private T? _relatedObject;
public async Task<T?> GetRelatedObject()
{
return _relatedObject ?? await LazyLoad();
}
internal DiscosObjectRelationship(string linkAddress, IDiscosClient client)
{
_linkAddress = linkAddress;
_client = client;
}
private async Task<T?> LazyLoad()
{
_relatedObject = (await _client.Get<T>(_linkAddress))?.Attributes;
return _relatedObject;
}
}
本质上,我想要它做的就是将 _linkAddress
设置为 Faker.Net
中的随机 URL 并将 _client
设置为 [=18 中的模拟=].我试过这样做:
public class DiscosRelationshipSpecimenBuilder: ISpecimenBuilder
{
public object Create(object request, ISpecimenContext context)
{
if (request is Type {IsGenericType: true} type && type.GetGenericTypeDefinition() == typeof(DiscosObjectRelationship<>))
{
return Activator.CreateInstance(type, Faker.Internet.Url(), Substitute.For<IDiscosClient>()) ?? new NoSpecimen();
}
return new NoSpecimen();
}
}
但是,它会抛出一个错误,提示无法找到该类型的构造函数。这让我感到困惑(据我所知)我提供了正确的参数(分别为 string
和 IDiscosClient
)。
完整的例外是:
System.MissingMethodException: Constructor on type 'DISCOSweb_Sdk.Models.Relationships.DiscosObjectRelationship`1[[DISCOSweb_Sdk.Models.ResponseModels.Reentries.Reentry, DISCOSweb-Sdk, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]' not found.
at System.RuntimeType.CreateInstanceImpl(BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture)
at System.Activator.CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes)
at System.Activator.CreateInstance(Type type, Object[] args)
at DISCOSweb_Sdk.Tests.Fixtures.AutoFixture.DiscosRelationshipSpecimenBuilder.Create(Object request, ISpecimenContext context) in /home/james/repos/DISOSweb-sdk/src/DISCOSweb-Sdk/DISCOSweb-Sdk.Tests/Fixtures/AutoFixture/DiscosRelationshipSpecimenBuilder.cs:line 17
at AutoFixture.Kernel.CompositeSpecimenBuilder.Create(Object request, ISpecimenContext context)
at AutoFixture.CustomizationNode.Create(Object request, ISpecimenContext context)
at AutoFixture.Kernel.CompositeSpecimenBuilder.Create(Object request, ISpecimenContext context)
at AutoFixture.Kernel.TerminatingWithPathSpecimenBuilder.Create(Object request, ISpecimenContext context)
我做错了什么?
Activator.CreateInstance()
默认只查找 public 构造函数。如果要查找构造函数的其他范围,则需要使用 BindingFlags
.
的重载
需要的标志是:
const BindingFlags flags = BindingFlags.NonPublic | BindingFlags.Instance;
您可能还想使用 InvariantCulture
,因此整个调用类似于:
return Activator.CreateInstance(type, flags, null, new object[] {myArgs}, CultureInfo.InvariantCulture;)
我正在尝试为此 class 创建一个 AutoFixture.ISpecimenBuilder
:
public class DiscosObjectRelationship<T> where T : DiscosModelBase
{
private readonly string _linkAddress;
private readonly IDiscosClient _client;
private T? _relatedObject;
public async Task<T?> GetRelatedObject()
{
return _relatedObject ?? await LazyLoad();
}
internal DiscosObjectRelationship(string linkAddress, IDiscosClient client)
{
_linkAddress = linkAddress;
_client = client;
}
private async Task<T?> LazyLoad()
{
_relatedObject = (await _client.Get<T>(_linkAddress))?.Attributes;
return _relatedObject;
}
}
本质上,我想要它做的就是将 _linkAddress
设置为 Faker.Net
中的随机 URL 并将 _client
设置为 [=18 中的模拟=].我试过这样做:
public class DiscosRelationshipSpecimenBuilder: ISpecimenBuilder
{
public object Create(object request, ISpecimenContext context)
{
if (request is Type {IsGenericType: true} type && type.GetGenericTypeDefinition() == typeof(DiscosObjectRelationship<>))
{
return Activator.CreateInstance(type, Faker.Internet.Url(), Substitute.For<IDiscosClient>()) ?? new NoSpecimen();
}
return new NoSpecimen();
}
}
但是,它会抛出一个错误,提示无法找到该类型的构造函数。这让我感到困惑(据我所知)我提供了正确的参数(分别为 string
和 IDiscosClient
)。
完整的例外是:
System.MissingMethodException: Constructor on type 'DISCOSweb_Sdk.Models.Relationships.DiscosObjectRelationship`1[[DISCOSweb_Sdk.Models.ResponseModels.Reentries.Reentry, DISCOSweb-Sdk, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]' not found.
at System.RuntimeType.CreateInstanceImpl(BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture)
at System.Activator.CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes)
at System.Activator.CreateInstance(Type type, Object[] args)
at DISCOSweb_Sdk.Tests.Fixtures.AutoFixture.DiscosRelationshipSpecimenBuilder.Create(Object request, ISpecimenContext context) in /home/james/repos/DISOSweb-sdk/src/DISCOSweb-Sdk/DISCOSweb-Sdk.Tests/Fixtures/AutoFixture/DiscosRelationshipSpecimenBuilder.cs:line 17
at AutoFixture.Kernel.CompositeSpecimenBuilder.Create(Object request, ISpecimenContext context)
at AutoFixture.CustomizationNode.Create(Object request, ISpecimenContext context)
at AutoFixture.Kernel.CompositeSpecimenBuilder.Create(Object request, ISpecimenContext context)
at AutoFixture.Kernel.TerminatingWithPathSpecimenBuilder.Create(Object request, ISpecimenContext context)
我做错了什么?
Activator.CreateInstance()
默认只查找 public 构造函数。如果要查找构造函数的其他范围,则需要使用 BindingFlags
.
需要的标志是:
const BindingFlags flags = BindingFlags.NonPublic | BindingFlags.Instance;
您可能还想使用 InvariantCulture
,因此整个调用类似于:
return Activator.CreateInstance(type, flags, null, new object[] {myArgs}, CultureInfo.InvariantCulture;)