【问题标题】:Generic Abstract class who inherits members from Passed Type Parameter从传递的类型参数继承成员的通用抽象类
【发布时间】:2017-02-15 03:40:08
【问题描述】:

我正在尝试找出一种方法来抽象我的适配器逻辑。我想要一个从传递给它的成员继承的通用抽象类。

public interface IAdaptable<in TIEntity, in TIDTO, TDTO>
    where TDTO : TIDTO
{
    void Initialize(TIEntity entity);
    TDTO ToDTO();
}

public interface IAdaptable<in TIEntity, TDTO> : IAdaptable<TIEntity, TDTO, TDTO>
{
}

public abstract class AdapterBase<TEntity, TIDTO, TDTO> : IAdaptable<TEntity, TIDTO, TDTO>, TIDTO
    where TDTO : TIDTO
{
    protected TEntity entity;

    public void Initialize(TEntity entity)
    {
         this.entity = entity;
    }

    public TDTO ToDTO()
    {
        return Mapper.Map<TIDTO, TDTO>(this);
    }
} 

此代码不起作用,因为您不能从传入的通用参数继承,即使 id 像我的父类一样强制执行它。

如果有人想知道这里为什么或发生了什么,这个适配器基础应用于必须实现 DTO 的接口属性的适配器,然后将附加逻辑应用于 getter 和设置以防止 id 篡改并执行一些操作基本设置逻辑。

如果我手动将其应用于每个适配器,此代码工作正常,但我更喜欢适配器库或代理而不是适配器库,它将为我处理所有这些逻辑。

有谁知道我可以抽象这个逻辑的方法,或者解决问题,这样我就不必手动将此逻辑应用于每个适配器?

【问题讨论】:

  • 我相信城堡动态代理是实现这一目标的唯一方法,但我可能错了。
  • @inquisitive 谢谢你的提示,我会调查这些是什么
  • 你确定这是一个错字:public abstract class AdapterBase&lt;TEntity, TDTO&gt; : IAdaptable&lt;TEntity, TDTO&gt; TIDTO最后一个TIDTO
  • @CodingYoshi 那是我的错误我原来写的问题没有接口,但后来我把它们放进去更清楚我现在会更新它
  • 对不起,我在遇到问题时删除了原来的类我只是从内存中重新创建问题,我删除了一些其他接口方法来解决问题

标签: c# generics inheritance abstract-class covariance


【解决方案1】:

对于那些想要答案的人,我已经找到了解决方案,但您可能不喜欢它。

这是完整的界面:

public interface IAdaptable<in TIEntity, in TIDTO, TDTO>
    where TDTO : TIDTO
{
    bool IsInitialized { get;  set; }
    void Initialize(TIEntity entity);
    TDTO ToDTO(TIDTO iEntityDTO);
    void ApplyFrom(TIDTO entityDTO);
}

现在您可以像这样创建适配器基础:

public class AdapterBase<TIEntity, TIDTO, TDTO> : IAdaptable<TIEntity, TIDTO, TDTO>
    where TDTO : TIDTO
{
    #region Consts

    public const string FAILED_TO_INITIALIZE_ADAPTER_ERROR = "Failed to Initialize Adapter make sure you called the Initialize function";

    #endregion

    #region Protected Members

    protected TIEntity _entity;

    #endregion

    #region IAdaptable

    public bool IsInitialized { get; set; }

    public void Initialize(TIEntity entity)
    {
        this._entity = entity;
        IsInitialized = true;
    }

    public void ApplyFrom(TIDTO entityDTO)
    {
        if (false == IsInitialized)
        {
            throw new Exception(FAILED_TO_INITIALIZE_ADAPTER_ERROR);
        }

        Mapper.Map(entityDTO, this);

    }

    public TDTO ToDTO(TIDTO adaptable)
    {
        if (false == IsInitialized)
        {
            throw new Exception(FAILED_TO_INITIALIZE_ADAPTER_ERROR);
        }

        return Mapper.Map<TIDTO, TDTO>(adaptable);
    }

    #endregion
}

现在您可以像这样在通用的 crud 服务中使用您的适配器

public class AsyncCRUDService<TEntity, TIDTO, TDTO, TAdapter> : IAsyncCRUDService<TDTO>
    where TDTO : TIDTO
    where TEntity : class, new()
    where TAdapter : class, TIDTO, IAdaptable<TEntity, TIDTO, TDTO>
{
    protected DbContext _context;
    protected TAdapter _adapter;

    public AsyncCRUDService(DbContext context, TAdapter adapter)
    {
        this._context = context;
        this._adapter = adapter;
    }

    public async virtual Task<TDTO> Get(object[] id)
    {
        var entity = await this._context.Set<TEntity>().FindAsync(id);

        if (null == entity)
        {
            throw new InvalidIdException();
        }
        return this.AdaptToDTO(entity);
    }

    protected virtual TDTO AdaptToDTO(TEntity entity)
    {
        this._adapter.Initialize(entity);
        return this._adapter.ToDTO(this._adapter);
    }

}

唯一的缺点是现在您的服务与硬依赖相关联

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多