2016-03-23 195 views
3

泛型類型我有這樣一個結構實例化泛型方法

void Main() 
{ 
    var lol = ActionClass.GetTestTuple<Request, Response, RequestCallInfo>("lol", "user"); 
    lol.Dump(); 
} 

public class ActionClass 
{ 
    public static Tuple<TRes, TInfo> GetTestTuple<TReq, TRes, TInfo>(string resultMsg, string userName) 
    where TReq : BaseRequest, new() 
    where TRes : BaseResponse, new() 
    where TInfo : CallInfo<TReq>, new() 
    { 
     var response = new TRes { Message = resultMsg }; 
     var eventsInfo = new TInfo(); 
     eventsInfo.Data.UserName = userName; 

     return new Tuple<TRes, TInfo>(response, eventsInfo); 
    } 
} 

public class Request : BaseRequest 
{ 
} 

public class Response : BaseResponse 
{ 
} 

public class RequestCallInfo : CallInfo<Request> 
{ 
    public string Item { get; set; } 
} 

public class CallInfo<GenericType> : BaseCallInfo where GenericType : BaseRequest, new() 
{ 
    public GenericType Data { get; set; } 

    public CallInfo(GenericType x) 
    { 
     Data = x; 
    } 
} 

public class BaseCallInfo 
{ 
    public string CallItem { get; set; } 
} 

public class BaseRequest 
{ 
    public string UserName { get; set; } 
} 

public class BaseResponse 
{ 
    public string Message { get; set; } 
} 

,當我執行它,我得到UserQuery.CallInfo<UserQuery.Request> does not contain a constructor that takes 0 arguments,

所以我想這樣

public static Tuple<TRes, TInfo> GetTestTuple<TReq, TRes, TInfo>(string resultMsg, string userName) 
    where TReq : BaseRequest, new() 
    where TRes : BaseResponse, new() 
    where TInfo : CallInfo<TReq>, new() 
{ 
    var response = new TRes { Message = resultMsg }; 
    var eventsInfo = new TInfo(new TReq { UserName = userName }); 
    eventsInfo.Data.UserName = userName; 

    return new Tuple<TRes, TInfo>(response, eventsInfo); 
} 

,但我獲得'TInfo': impossible to provide arguments when instantiating a type

我該如何通過的實例到TInfo並只保留參數構造函數CallInfo<GenericType>

+0

OT:簽名約束是在規格爲C#7。我真的希望他們不要再拋棄它。 – Dbl

回答

1

new()約束只要求泛型類型具有公共無參數構造函數;沒有辦法在C#中的泛型類型/約束上指定特定的構造簽名。鑑於此,編譯器無法知道調用者可以使用哪些構造函數,因此您無法使用構造函數參數實例化泛型類型。

所以,你可以使用反射在這裏,如果你想,但根據您所提供的代碼,這個解決方法看起來簡單:

var eventsInfo = new TInfo() { Data = new TReq { UserName = userName } }; 
+0

如果我們可以在Interfaces上聲明構造函數,那將會非常好。 –

+1

@MatthewWhited這可以很容易地與工廠解決 –

+0

@CodingGorilla它一直說我需要參數較少的構造函數。有沒有辦法讓它工作並保持構造函數的參數? – Phate01

0

您應該使用Activator.CreateInstance方法。

工作溶液:

public class ActionClass 
{ 
    public static Tuple<TRes, TInfo> GetTestTuple<TReq, TRes, TInfo>(string resultMsg, string userName) 
     where TReq : BaseRequest, new() 
     where TRes : BaseResponse, new() 
     where TInfo : CallInfo<TReq> 
    { 
     var response = new TRes { Message = resultMsg }; 
     var eventsInfo = (TInfo)Activator.CreateInstance(typeof(TInfo), new []{ new TReq() }); 
     eventsInfo.Data.UserName = userName; 

     return new Tuple<TRes, TInfo>(response, eventsInfo); 
    } 
} 

public class BaseCallInfo 
{ 
    public string CallItem { get; set; } 
} 

public class BaseRequest 
{ 
    public string UserName { get; set; } 
} 

public class BaseResponse 
{ 
    public string Message { get; set; } 
} 

public class Request : BaseRequest 
{ 
} 

public class Response : BaseResponse 
{ 

} 

public class RequestCallInfo : CallInfo<Request> 
{ 
    public string Item { get; set; } 

    public RequestCallInfo(Request x) : base(x) 
    { 

    } 
} 

public class CallInfo<GenericType> : BaseCallInfo where GenericType : BaseRequest, new() 
{ 
    public GenericType Data { get; set; } 

    public CallInfo(GenericType x) 
    { 
     Data = x; 
    } 
} 

}

+2

由於有幾個人對另一個答案進行了評論,所以這將**在運行時失敗**任何沒有匹配構造函數簽名的類。雖然這將在OP提供的特定代碼的情況下工作,但這是一種非常糟糕的做法(IMO),因爲它會向將來不知道此代碼的另一個'CallInfo '的實現者提出潛在的錯誤。 – CodingGorilla