I'm using SpecFlow, and I want to shove proxy in the service registrations from IServiceCollection
so that ScenarioContext.ScenarioContainer
can resolve them.
The strategy I'm trying to use is simply to register a factory for each of the types defined in the service collection so that the ScenarioContainer can resolve them. Unfortunately for me, there is no non-generic alternative to RegisterFactoryAs
, so I'm trying to create a generic method and invoke it via reflection.
Where I'm hitting a wall is the arguments to MethodBase.Invoke
: the first argument to RegisterFactoryAs
is a Func<IObjectContainer, T>
, and I'm encountering two problems with it:
- I cannot define it as
Func<IObjectContainer, T> factory = _ => ...
since I don't have an outer-scoped T. - When attempting to use it as
Func<IObjectContainer, object>
, I the run-time exception "System.InvalidOperationException : Late bound operations cannot be performed on types or methods for which ContainsGenericParameters is true." - When attempting to use the local function
FactoryFunction
, I see a compile error stating that I can't convert a method group into an object.
My best bet seems to be the local function, if I can somehow convert it into the required Func
.
private void AddToObjectContainer2(IServiceCollection services)
{
var sp = services.BuildServiceProvider();
foreach (var sd in services)
{
var containerType = _scenarioContext.ScenarioContainer.GetType();
var delegateType = typeof(Func<,>).MakeGenericType(typeof(IObjectContainer), sd.ServiceType);
var methodInfo = containerType
.GetMethod(nameof(IObjectContainer.RegisterFactoryAs),
new[]
{
delegateType,
typeof(string)
});
var registerFactoryAs = methodInfo
!.MakeGenericMethod(new[]
{
sd.ServiceType
});
Func<IObjectContainer, T> factoryWithCompileError = _ =>
{
return sp.GetService(sd.ServiceType);
};
Func<IObjectContainer, object> factory = _ =>
{
return sp.GetService(sd.ServiceType);
};
T FactoryFunction<T>(IObjectContainer c)
{
return (T)sp.GetService(sd.ServiceType);
}
// Throws System.InvalidOperationException : Late bound operations cannot be performed on types or methods for which ContainsGenericParameters is true.
registerFactoryAs.Invoke(_scenarioContext.ScenarioContainer,
new object[]
{
factory , (string)null
});
// Compiler error: Cannot convert expression of type 'method group' to type 'object'
registerFactoryAs.Invoke(_scenarioContext.ScenarioContainer,
new object[]
{
FactoryFunction , (string)null
});
}
}
I tried to use https://github.com/solidtoken/SpecFlow.DependencyInjection, but it can't seem to handle one of the auto-registered types we're using that has an internal implementation in the Specflow library.
I tried https://github.com/AdCodicem/SpecFlowMicrosoftDependencyInjection, but apparently the signature of a method of one of its dependencies has been removed, and it's throwing a MethodNotFoundException at runtime.
Aucun commentaire:
Enregistrer un commentaire