makerofthings7
makerofthings7

Reputation: 61473

Cannot provide arguments when creating an instance of generic type

I have an object that I want to have read only after it is created... namely because the properties in the constructor must be used in GetHashCode, and therefore can't change once created.

I this is one of many classes that are readonly:

public class AccountLabel
{ 
    private string result;

    public AccountLabel(string result)
    {
        // TODO: Complete member initialization
        this.result = result;
    }

    public string JSONRPCData { get { return this.result; } }
}

I have a generic result class like this

  public  class JsonResult<T>  where  T : JObject, new()
  {
    private T bhash;
    private string p;
    private JsonErrorResponse error;
    private int _id;
    private Newtonsoft.Json.Linq.JObject ret;

    public JsonResult(Newtonsoft.Json.Linq.JObject ret)
    { 
        this.ret = ret;

        var tempError = ret["error"];
        var tempid = ret["id"];
        JsonErrorResponse error = new JsonErrorResponse(tempError);
        this.error = error;
        this._id = 1;


        var tempresult = ret["result"];
        T someResult = new T(tempresult);  // <--- here is my problem
    }

My problem is that I want to pass an object into T's constructor but can't. When I type this the compiler tells me Cannot provide arguments when creating an instance of variable type

What is the best way to work around this situation?

Upvotes: 20

Views: 8975

Answers (2)

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726929

You can remove the new type constraint, and use Activator.CreateInstance instead.

Instead of this

T someResult = new T(tempresult);

write this:

T someResult = (T)Activator.CreateInstance(
    typeof(T)
,   new object[] { tempresult }
);

This is likely to be somewhat slower because of going through reflection, and the static checks by the compiler would not be performed. However, considering your scenario, it does not look like either of these would present a significant problem.

Upvotes: 34

jam40jeff
jam40jeff

Reputation: 2596

You could pass in a factory delegate to the constructor of JSonResult<T>:

public class JsonResult<T> where T : JObject
{
    public JsonResult(Newtonsoft.Json.Linq.JObject ret, Func<object, T> factory)
    { 
        var tempresult = ret["result"];
        T someResult = factory(tempresult);
    }
}

object in Func<object, T> could be replaced with whatever the type of tempResult actually is.

Upvotes: 8

Related Questions