【问题标题】:Retrieve generic class from collection based on another type从基于另一种类型的集合中检索泛型类
【发布时间】:2018-06-13 01:07:56
【问题描述】:

我在实现将一些 CRUD 逻辑和 dto-entity 映射封装在单独的服务中的解决方案时遇到了麻烦,我真的可以使用一些帮助。

假设我们有下一个接口,它提供对数据存储的访问端点,并且每个实体都有一个单独的客户端

public interface IClient<T> where T : class
{
    T Get();
    void Set(T entity);
}

然后我们将 ClientService 用作聚合器,为所有现有客户端提供单一访问点

public class A { };
public class B { };

public class ClientService
{
    private IDictionary<Type, object> _clientDict;

    public ClientService(IClient<A> clientA, IClient<B> clientB)
    {
        _clientDict = new Dictionary<Type, object>
        {
            { typeof(A), clientA },
            { typeof(B), clientB }
        };
    }

    public T Get<T>() where T : class
    {
        var client = this.GetClient<T>();
        return client.Get();
    }

    public void Set<T>(T entity) where T : class
    {
        var client = this.GetClient<T>();
        client.Set(entity);
    }

    private IClient<T> GetClient<T>() where T : class
    {
        if (_clientDict.TryGetValue(typeof(T), out object client))
        {
            return (IClient<T>)client;
        }

        throw new ArgumentException();
    }
}

到目前为止一切都很好。

现在的问题。我需要将其转换为使用 DTO 对象以使用 IClient&lt;T&gt;,同时仍接受非 DTO 模型到 ClientService。 伪代码:

public class A { };
public class A_DTO { };
public class B { };
public class B_DTO { };

public class ClientService
{
    private IDictionary<Type, object> _clientDict;

    public ClientService(IClient<A_DTO> clientA, IClient<B_DTO> clientB)
    {
        _clientDict = new Dictionary<Type, object>
        {
            { typeof(A), clientA },
            { typeof(B), clientB }
        };
    }

    public void Set<T>(T entity) where T : class
    {
        var dtoType = GetDTOType(T);
        var dtoEntity = _autoMapper.Map(entity, typeof(T), GetDTOType(T));

        var client = this.GetClient<T, dtoType>();
        client.Set(dtoEntity);
    }

    private IClient<DTO> GetClient<T, DTO>() where T : class
                                            where DTO: class
    {
        if (_clientDict.TryGetValue(typeof(T), out object client))
        {
            return (IClient<DTO>)client;
        }

        throw new ArgumentException();
    }
}

我确实理解,由于泛型在编译期间被解析,我们无法使它们依赖于变量,但可能有任何其他方式可以让客户端使用,即是否存在我们如何实现IClient&lt;T2&gt; GetClient&lt;T1, T2&gt;,其中T1AT2A_DTO? 请注意,最终用户无权访问 DTO 对象,因此无法将其作为通用类型提供,一切都需要在内部进行。

是否有任何通用实现,或者我只是在浪费时间,应该为每个客户端实现创建特定方法(即Get&lt;A&gt;()Get&lt;B&gt; 等)?

【问题讨论】:

    标签: c# .net generics .net-core polymorphism


    【解决方案1】:

    您实际上并不需要在您的客户服务类中包含您的 DTO。一旦你的模型开始增长,那肯定会变得一团糟。相反,您可以使用AutoMapper 之类的工具将结果从您的服务类转换为您的 dto。这很简单。你可以有这样的东西:

    public class A { };
    
    public class DtoA { };
    
    var source = ServiceClass.Get<A>();
    var dto = Mapper.Map<A, ADto>(source);
    

    查看链接了解更多详情。

    【讨论】:

    • 谢谢,但如果你看到我已经在我的示例中使用了 automapper:var dtoEntity = _autoMapper.Map(entity, typeof(T), GetDTOType(T));。我的观点是业务逻辑不会知道 DTO,所以我想看看是否可以以通用方式将转换封装在服务中。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-03-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多