0

I want to dynamically create an instance of a model and return results like below. How can I do this?

public JsonResult GetDetail(string model, int id)
{
    Type type = Type.GetType("MyProject.WebApplication.Models.MyProjctContext." + model);            
    var result = (type)Activator.CreateInstance(type).Find(id);

    return Json(new
    {
        data = result
    },
    JsonRequestBehavior.AllowGet);
}
3
  • What does that give you? That looks close to something that should work without doing too much with it. Commented Aug 1, 2014 at 18:54
  • 1
    I'd think twice about the security aspects of implementing something like this. You're essentially giving direct, unrestricted access to your data layer. Commented Aug 1, 2014 at 19:00
  • Add a GetDetail<T> method and overload with a method that takes the type and passes it to a switch/case. But I'm biased to having hardcoded strings in code when you have other alternatives. Commented Aug 1, 2014 at 19:45

2 Answers 2

1
var result = (type)Activator.CreateInstance(type).Find(id);
  1. CreateInstance(Type) returns an object which doesn't contains a Find(int) method that I believe is found on your model.
  2. You can't type cast via a type variable, unless it is a specified type in a generic method or generic class method.

This could be fixed by using reflexion, interface :

    public JsonResult GetDetail(string modelTypeName, int id)
    {
        var type = Type.GetType("MyProject.WebApplication.Models.MyProjctContext." + modelTypeName);            

        //reflection way
        var model = Activator.CreateInstance(type);
        var result = (*find method return type*)type.GetMethod("Find", new Type[] { int }).Invoke(model, new object[] { id });

        //constraint way : with constraint being an interface or a base class that defines .Find(int)
        var result = ((*constraint*)Activator.CreateInstance(type)).Find(id);


        return Json(new
            {
                data = result
            },
            JsonRequestBehavior.AllowGet);
    }

or using dynamic as Marnix van Valen suggested.

Sign up to request clarification or add additional context in comments.

2 Comments

How would that work with in MVC then? I don't think there's a mechanism in MVC routing and modelbinding that allows a request to be mapped to a generic action method.
@MarnixvanValen Indeed, I overlooked that. Thanks for pointing it out.
1

The only real problem in this code is the cast to type. If your data access layer would implement an interface with the method object Find(int id) you could simply cast to that interface. Otherwise I would recommend casting to dynamic and let the call be resolved at runtime.

public JsonResult GetDetail(string model, int id)
{
    Type type = Type.GetType("MyProject.WebApplication.Models.MyProjctContext." + model);            
    var result = ((dynamic)Activator.CreateInstance(type)).Find(id);

    return Json(new
    {
        data = result
    },
    JsonRequestBehavior.AllowGet);
}

A couple of remarks about this code:

  • Performance will likely not be brilliant.
  • This code will blow up if the type does not implement a Find(int) method
  • Think hard about the security implications of this code. At the very least, limit what entities can be requested through this action.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.