在泛型方法中调用特定的实现 [英] Calling a particular implementation inside a generic method

查看:108
本文介绍了在泛型方法中调用特定的实现的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在尝试实现一种通用方法,以将来自外部服务的DTO调整到我的Servisse模型中,但遇到了一个问题. 首先,让我将问题具体化. 假设外部服务将以下DTO返回到我的应用程序.

I'm currently trying to implement a generic method to adapt a DTO that comes from an external service into a model of my servisse and I ran into an issue. First let me just contextualize the problem. Let's say that an external service returns the following DTO to my application.

public class ExampleDTO
{
    public int Field1 { get; set; }
    public int Field2 { get; set; }
}

这是我的模特.

public class ExampleModel
{
    public int Field1 { get; set; }
    public int Field2 { get; set; }
}

如果我想将第一个类改编到我的模型中,我可以简单地编写以下方法:

If I wanted to adapt the first class into my model I could just simply write the following method:

public ExampleModel Adapt(ExampleDTO source)
{
    if (source == null) return null;

    var target = new ExampleModel()
    {
        Field1 = source.Field1,
        Field2 = source.Field2
    };

    return target;
}

现在让我们说,当我们获得ExampleDTO的集合时,该服务将返回以下类,而不仅仅是返回ICollection类型的集合:

Now let's say that when we get a collection of ExampleDTOs, the service instead of just returning a collection of type ICollection, returns the following class:

public class PagedCollectionResultDTO<T>
{
   public List<T> Data { get; set; }
   public int Page     { get; set; }
   public int PageSize { get; set; }
   public int Total    { get; set; }
}

示例" DTO的列表位于数据"字段中,页码,页大小和记录总数位于其余字段中.

Where the list of ExampleDTOs comes on the Data field and the page number, page size and total number of records comes on the rest of the fields.

我正在尝试实现一种通用方法,以使此类适合我自己的模型,该模型具有相同的结构.我想独立于数据字段的T类型执行此操作.

I'm trying to implement a generic method to adapt this class to my own model, which has the same structure. I want to do this independently of the type T of the Data field.

public class PagedCollectionResult<T>
{
    public List<T> Data { get; set; }
    public int Page     { get; set; }
    public int PageSize { get; set; }
    public int Total    { get; set; }

    public PagedCollectionResult() => (Data, Page, PageSize, Total) = (new List<T>(), 0, 0, 0);
}

我尝试了以下方法,其中尝试将DTO分页结果(S)调整为模型分页结果(T):

I've tried the following method, where I try to adapt the DTO paged result (S) into the model paged result (T) :

public PagedCollectionResult<T> Adapt<S,T>(PagedCollectionResultDTO<S> source) 
{
    if (source == null) return null;

    var target = new PagedCollectionResult<T>();

    foreach (var item in source.Data)
        target.Data.Add(this.Adapt(item));

    target.Page     = source.Page;
    target.PageSize = source.PageSize;
    target.Total    = source.Total;

    return target;
}

问题是我在该行中遇到错误:

The thing is that I'm getting an error in the line:

target.Data.Add(this.Adapt(item));

它不能将S转换为ExampleDTO. 如果我在Adapt上对ExampleDTO/ExampleModel设置了限制,则不再通用. 有没有一种方法可以为特定类型调用Adapt(item)方法?

It says that it can't convert S into ExampleDTO. If I put a restriction for ExampleDTO/ExampleModel on Adapt this isn't generic anymore. Is there a way to call the Adapt(item) method for the specific type?

这是我完整的TypeAdapter:

This is my complete TypeAdapter:

public class TypeAdapter
{
    public PagedCollectionResult<T> Adapt<S,T>(PagedCollectionResultDTO<S> source) 
    {
        if (source == null) return null;

        var target = new PagedCollectionResult<T>();

        foreach (var item in source.Data)
            target.Data.Add(this.Adapt(item));

        target.Page     = source.Page;
        target.PageSize = source.PageSize;
        target.Total    = source.Total;

        return target;
    }

    public ExampleModel Adapt(ExampleDTO source)
    {
        if (source == null) return null;

        var target = new ExampleModel()
        {
            Field1 = source.Field1,
            Field2 = source.Field2
        };

        return target;
    }
}

推荐答案

谢谢大家的回应,他们帮助我朝正确的方向前进. 我在运行时使用反射来解决正确的适应方法. 感谢您,我学到了一些有关反射的知识. 我正在分享解决方案,希望我也能有所作为. 这就是我最后得到的.

Thank you all for your responses, they helped me getting in the right direction. I used reflection at runtime to resolve the right adapt method. I learned a few things about reflection thanks to you. I'm sharing the solution in hope I can also give something back. This is what I ended up with.

public PagedCollectionResult<T> Adapt<S, T>(PagedCollectionResultDTO<S> source)
{
    if (source == null)
    {
        return null;
    }

    var target = new PagedCollectionResult<T>();

    // Get the type of S at runtime
    Type[] types = { typeof(S) };

    // Find the Adapt method on the TypeAdapter class that accepts an object of type S
    var adaptMethod = typeof(TypeAdapter).GetMethod("Adapt", types);

    foreach (var item in source.Data)
    {
        // for each item call the adapt method previously resolved and pass the item as parameter
        var parameters = new object[] { item };
        target.Data.Add((T)adaptMethod.Invoke(this, parameters));
    }

    target.Page = source.Page;
    target.PageSize = source.PageSize;
    target.Total = source.Total;

    return target;
}

这篇关于在泛型方法中调用特定的实现的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆