20

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?

  • Should I have an Interface that I can call that will update the property?

  • Will that previous Interface break encapsulation or allow changes to be made to my object?

  • How else should I approach this?

2
  • 2
    you could create a Factory class that knows how to create T (so JsonResult would call MyFactory<T>.create(tempresult) instead of using new Commented Dec 16, 2012 at 20:58
  • I have edited your title. Please see, "Should questions include “tags” in their titles?", where the consensus is "no, they should not". Commented Dec 16, 2012 at 20:58

2 Answers 2

34

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.

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

Comments

8

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.

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.