繁体   English   中英

在泛型方法中实例化泛型类型

[英]instantiate generic type in generic method

我有这样的结构

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实例TReqTInfo并仅在CallInfo<GenericType>保留参数构造函数?

new()约束只要求泛型类型具有公共参数构造函数; 无法在C#中的泛型类型/约束上指定特定的构造签名。 鉴于此,编译器无法知道调用者可以使用哪些构造函数,因此您无法使用构造函数参数实例化泛型类型。

因此,如果您愿意,可以在此处使用反射,但根据您提供的代码,此解决方案似乎更简单:

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

您应该使用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;
    }
}

}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM