2016-03-23 4 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

Как сдать экземпляр TReq - TInfo и сохраните только конструктор параметров в CallInfo<GenericType>?

+0

OT: подписные ограничения в спецификации для C# 7. я действительно надеюсь, что они больше не откажут это. – Dbl

ответ

1

Ограничение new() требует, чтобы общий тип имел открытый конструктор без параметров; нет способа указать конкретные сигнатуры конструкции для общего типа/ограничения в C#. Учитывая это, компилятор не может знать, какие конструкторы будут доступны вызывающим абонентам, поэтому вы не можете создавать типичный тип с использованием параметров конструктора.

Таким образом, вы могли бы использовать отражение здесь, если вы хотите, но это решение кажется проще на основе кода предоставленной Вами:

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

Было бы так приятно, если бы мы могли объявить конструкторы на интерфейсах. –

+1

@MatthewWhited Это может быть легко обработано с заводами –

+0

@CodingGorilla продолжает говорить, что мне нужен конструктор less less. Есть ли способ заставить его работать и сохранить конструктор с параметром? – 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

Смежные вопросы