从Passed Type Parameter继承成员的Generic Abstract类

时间:2017-02-15 03:40:09

标签: c# generics inheritance abstract-class covariance

我试图想出一种抽象我的适配器逻辑的方法。我希望有一个Generic Abstract类继承自传递给它的成员。

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被篡改并做一些基本设定逻辑。

如果我手动将它应用到每个适配器,但是这个代码可以正常工作,但是id更喜欢适配器库或代理服务器基础,它将为我处理所有这些逻辑。

有没有人知道我可以抽象这种逻辑的方法,或者解决这个问题,所以我不必手动将这个逻辑应用到每个适配器上?

1 个答案:

答案 0 :(得分:0)

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

这是完整的界面:

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);
    }

}

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

相关问题