LightInject
LightInject copied to clipboard
InvalidCastException (PCL_111 and NET45) when resolving type with a `Func<>` in runtime arguments
InvalidCastException (PCL_111 and NET45) when resolving type with a Func<> in runtime arguments
We have some types which are registered using delegate factories. An example could be:
public Foo(long? lng1, long? lng2, string str1, string str2, Func<int, int> func = null)
{
Lng1 = lng1;
Lng2 = lng2;
Str1 = str1;
Str2 = str2;
Func = func;
}
The type is registered like this:
var context = new IocContext();
context.RegisterObject<long?, long?, string, string, Func<int, int>, Foo>((lng1, lng2, str1, str2, func) =>
{
return new Foo(lng1, lng2, str1, str2, func);
});
... where IocContext is an abstraction on top of LightInject:
public class IocContext
{
...
public void RegisterObject<T1, T2, T3, T4, T5, TSvc>(Func<T1, T2, T3, T4, T5, TSvc> factoryFunc, string name = null)
{
RegisterServiceFromDelegate(typeof(TSvc), factoryFunc, name ?? typeof(TSvc).Name);
}
private void RegisterServiceFromDelegate(Type type, Delegate factory, string serviceName)
{
var serviceRegistration = new ServiceRegistration
{
ServiceType = type,
FactoryExpression = factory,
ServiceName = serviceName,
Lifetime = null
};
_serviceContainer.Register(serviceRegistration);
}
...
}
When resolving a registration that is given a Func<> on runtime:
Func<int, int> funcArg = x => x * 2;
var args = new object[] { 1L, 2L, "Hello1", "Hello2", funcArg };
// ----> InvalidCastException is thrown here <----
var iocFoo = context.ServiceContainer.GetInstance(typeof(Foo), typeof(Foo).Name, args) as Foo;
... we get an InvalidCastException similar to this:
System.InvalidCastException was unhandled
HResult=-2147467262
Message=Unable to cast object of type 'System.Int64' to type 'System.String'.
Source=LightInject
StackTrace:
at DynamicMethod(Object[] )
at LightInject.ServiceContainer.GetInstance(Type serviceType, String serviceName, Object[] arguments) in c:\Github\LightInject\src\LightInject\NuGet\tmp\Net45\Binary\LightInject\LightInject.cs:line 3049
at LightInjectDebug.Program.Sample1() in C:\Some\Path\LightInjectDebug\LightInjectDebug\Program.cs:line 37
at LightInjectDebug.Program.Main() in C:\Some\Path\LightInjectDebug\LightInjectDebug\Program.cs:line 19
at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
InnerException:
If we remove the Func<> from the runtime arguments (and from the resolved type's ctor) everything seems to work as expected.
I have included a sample application that:
- Illustrates this issue
- Shows an "interesting" observation when all provided runtime args are null
- Shows a work-around (.. but is not pretty)
If you need any more context, please let me know.
Please note Again, github won't let me upload .zip files, so I have added a .txt extension to get around that bug. You know what to do :)
Environment
- VS2015
- Windows 8.1 Enterprise x64
- LightInject 4.0.4 (nuget pkg)
- .NET 4.5.2
Sorry for the late reply. Your workaround is valid and if you can live with that for now that would be great :) It's kind of a rush to get things ready for ASP.NET 5 these days :)