C# 使用从内部子对象确定的类型实现泛型列表getter?

C# 使用从内部子对象确定的类型实现泛型列表getter?,c#,generics,C#,Generics,对于上下文,我正在为Navision web服务创建一个包装器类 其结构如下: class JobList_Service : SoapHttpClientProtocol { public Job[] ReadMultiple() { ... } } 我想做如下事情: var jobWS = new NavService<JobList_Service>(); jobWS.GetAll<Job>

对于上下文,我正在为Navision web服务创建一个包装器类

其结构如下:

class JobList_Service :  SoapHttpClientProtocol
{
        public Job[] ReadMultiple()
        {
             ...
        }
}
我想做如下事情:

var jobWS = new NavService<JobList_Service>();
jobWS.GetAll<Job>();
var jobWS=new NavService();
jobWS.GetAll();
我正在与泛型作斗争,我不知何故需要声明第二个类型,因为它将JobList_服务作为一个类型,因此返回一个JobList_服务列表,这不是我想要的

以下是我目前的实施情况:

public class NavService<T> where T :  SoapHttpClientProtocol, new()
{
    private T serviceInstance {get; set;}

    public NavService() 
    {
        serviceInstance = new T();
        ADSecurity.AuthenticateService_CurrentUser(serviceInstance);
    }


    public List<T> GetAll() 
    {
        try
        {
            MethodInfo method = serviceInstance.GetType().GetMethod("ReadMultiple");

            ParameterInfo[] paramTypes = method.GetParameters(); //We know that ReadMultiple takes three arguments, we will make that assumption here.
            var filter = Activator.CreateInstance(paramTypes[0].ParameterType, 0);
            object[] parameters = { filter, "", new Int32() };

            var ret =  (List<T>)/*Problem with this cast, obviously*/ method.Invoke(serviceInstance, parameters) ;
            return ret;


        } catch (Exception ex)
        {

            throw ex;
        }
    }

}
公共类导航服务,其中T:SoapHttpClientProtocol,new()
{
私有T服务实例{get;set;}
公共服务()
{
serviceInstance=newt();
ADSecurity.AuthenticateService\u CurrentUser(serviceInstance);
}
公共列表GetAll()
{
尝试
{
MethodInfo method=serviceInstance.GetType().GetMethod(“ReadMultiple”);
ParameterInfo[]paramTypes=method.GetParameters();//我们知道ReadMultiple接受三个参数,我们将在这里进行假设。
var filter=Activator.CreateInstance(paramTypes[0]。ParameterType,0);
object[]参数={filter,“,new Int32()};
var ret=(List)/*此强制转换存在问题,显然是*/method.Invoke(serviceInstance,parameters);
返回ret;
}捕获(例外情况除外)
{
掷骰子;
}
}
}
*编辑:如果有人能推荐一个更好的标题,请放心,我不知道正确的术语。

您可以用两个类型参数来解决这个问题-一个用于服务类型,一个用于响应类型:

public class NavService<T, TResponse>
{
    ...

    public List<TResponse> GetAll()
    {

    }
}
然后将其传递到
NavService
构造函数:

public class NavService<T>
{
    private IJobListService<T> _serviceInstance;

    public NavService(IJobListService<T> serviceInstance) 
    {
        _serviceInstance = serviceInstance;

        /* authenticate the service outside of this scope (i.e. before
         * it is passed to this ctor). This breaks encapsulation.
         * ADSecurity.AuthenticateService_CurrentUser(serviceInstance); */
    }

    public List<T> GetAll() { }
}
公共类导航服务
{
私有IJobListService\u serviceInstance;
公共导航服务(IJobListService服务实例)
{
_serviceInstance=serviceInstance;
/*在此范围之外对服务进行身份验证(即在
*它被传递给这个ctor)。这破坏了封装。
*ADSecurity.AuthenticateService\u CurrentUser(serviceInstance)*/
}
公共列表GetAll(){}
}
这加强了更好的封装,还应该防止您不得不进行所有不愉快的反射(您必须自己在这方面做一些额外的工作,因为我不知道具体类型的所有细节),并允许您只调用方法

编辑:因为您的评论指出您的服务是生成的,所以我将把您的每个服务包装在一个适配器中,您可以将接口应用到该适配器:

public class JobListService : IListService<Job>
{
    // Your generated service
    private readonly JobList_Service _service;

    ... // set up service in ctor or wherever

    public Job[] ReadMultiple()
    {
        return _service.ReadMultiple();
    }
}        
公共类JobListService:IListService
{
//您生成的服务
私有只读作业列表服务;
…//在ctor或任何位置设置服务
公共作业[]ReadMultiple()
{
return _service.ReadMultiple();
}
}        

Hmm,但是JobList\u服务是自动生成的代码,我不是需要在每次生成时将接口添加到它的声明中吗?我没有意识到这一点-在这种情况下,我不直接应用接口,而是编写一些小适配器来镜像方法签名,但实现接口,看起来我需要做一些关于如何做到这一点的研究,对泛型来说有点新。顺便说一下,接口部分是惊人的,非常干净的实现@大卫扩展了我的回答,以证明我的最后一句话:)
public class JobListService : IListService<Job>
{
    // Your generated service
    private readonly JobList_Service _service;

    ... // set up service in ctor or wherever

    public Job[] ReadMultiple()
    {
        return _service.ReadMultiple();
    }
}