问题
Reference: How can a dynamic be used as a generic?
public void CheckEntity(int entityId, string entityType = null)
{
dynamic AnyObject = Activator.CreateInstance("Assembly","Assembly.Models.DbModels." + entityType).Unwrap();
CheckWithInference(AnyObject, entityId);
}
private static void CheckWithInference<T>(T ignored, int entityId) where T : class
{
Check<T>(entityId);
}
private static void Check<T>(int entityId) where T : class
{
using (var gr = new GenericRepository<T>())
{
}
}
This enters with CheckEntity(16,"Container");. After the first line runs, AnyObject becomes a blank Assembly.Models.DbModels.Container when inspected with the debugger. If var AnyType = AnyObject.GetType(); is used, then AnyType shows as Assembly.Models.DbModels.Container. However, when the call to CheckWithInference(AnyObject, entityId); is made an exception is thrown.
I made a self-contained example here - but it runs without error :(
Note, this is in asp.net mvc 3 c#
HomeController.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace InferenceExample.Controllers
{
public class HomeController : Controller
{
//
// GET: /Home/
public ActionResult Index()
{
return View();
}
public void CheckEntity(int entityId, string entityType = null)
{
dynamic AnyObject = Activator.CreateInstance("InferenceExample", "InferenceExample.Models." + entityType).Unwrap();
CheckWithInference(AnyObject, entityId);
}
private static void CheckWithInference<T>(T ignored, int entityId) where T : class
{
Check<T>(entityId);
}
private static void Check<T>(int entityId) where T : class
{
var repo = new List<T>();
}
}
}
Example.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace InferenceExample.Models
{
public class Example
{
public int ExampleId { get; set; }
public string Name { get; set; }
}
}
Index.cshtml
@{
ViewBag.Title = "Index";
}
<h2>Index</h2>
@Html.ActionLink("Start", "CheckEntity", new { entityId = 16, entityType = "Example" })
I am at a loss. Why am getting this exception? I was unable to easily reproduce it. I am not sure what else to include for the example as this is all that the actual code has in it.
The really confusing part is that in the application, when this exception occurs, the action fails. However, upon revisiting the page and trying a second time, there is no exception thrown.
回答1:
As discussed in C# chat room, the solution here is to bypass dynamic entirely and use reflection to invoke the generic method. Dynamic has some nice features but sometimes causes more trouble than it's worth, especially when it's possible to get the Type object at runtime.
var modelType = Type.GetType("InferenceExample.Models." + entityType + ",InferenceExample");
var checkMethod = typeof(HomeController).GetMethod("CheckWithInference", BindingFlags.NonPublic | BindingFlags.Static);
checkMethod.MakeGenericMethod(modelType).Invoke(null, new object[] { entityId });
Glad to help :)
来源:https://stackoverflow.com/questions/12096695/getoriginaltypeparametertype-throws-object-reference-not-set-to-an-instance-of-a