无法在创建泛型类型实例时提供参数

20

我有一个对象,在创建后我希望它是只读的...这是因为构造函数中的属性必须在GetHashCode中使用,因此一旦创建就不能更改。

这是许多只读类之一:

public class AccountLabel
{ 
    private string result;

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

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

我有一个通用的结果类,就像这样

  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
    }

我的问题是我想将一个对象传递到T的构造函数中,但无法实现。当我这样输入时,编译器告诉我“创建变量类型实例时不能提供参数”。如何解决这种情况是最好的方法?
以下是几种解决方案:
1. 我可以创建一个接口,以便在其中调用更新属性的方法。
2. 之前提到的接口是否会破坏封装性或允许对我的对象进行更改?
3. 我还有其他方法来解决这个问题吗?

2
你可以创建一个工厂类,它知道如何创建T(因此JsonResult将调用MyFactory<T>.create(tempresult),而不是使用new)。 - Paolo Falabella
我已经编辑了你的标题。请参考“问题的标题应该包含“标签”吗?”,在那里达成共识是“不应该”。 - John Saunders
2个回答

34

您可以移除 new 类型约束,并使用 Activator.CreateInstance

替代代码:

T someResult = new T(tempresult);

请写下以下内容:

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

由于需要通过反射进行操作,这种方法可能会稍微慢一些,并且编译器的静态检查也不会执行。但是,考虑到您的情况,似乎这两个问题都不会造成重大问题。


8
您可以将工厂委托传递给 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);
    }
}

Func<object, T>中的object可以替换为tempResult实际的类型。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接