简体   繁体   中英

Generic Abstract class who inherits members from Passed Type Parameter

I'm trying to figure out a way to abstract my adapter logic. I want to have a Generic Abstract class who inherits from a member passed into it.

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

This Code Does not work because you cannot inherit from an generic paramter passed in, even though id like my parent class to enforce it.

Incase anyone is wondering why or what is happening here, this adapter base is applied to an adapter who must implement the the interface properties of the DTO, then additional logic is applied to the getters and setting to prevent id tampering and do some basic setting logic.

This code works fine if I apply it manually to each adapter but id prefer an adapter base or a proxy to an adapter base which will handle all of this logic for me.

Does anyone know of a way I can abstract this logic, or work around so I don't have to manually apply this logic to each adapter?

For Those of you who want the answer I've found a solution but you may not like it.

This is the full interface:

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

Which now you can create the adapter base like this:

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
}

Now you can use your adapter in a generic crud service like like so

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

}

The Only Downside is that now your services are tied to hard dependency

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM