Retrieving only fields from an implemented interface

24 views Asked by At

I have a class with fields added in IAuxiliary and ICachable. I want to return a list of objects but only want to share the fields which are in IAuxiliary.

    public interface IAuxiliary
{
    int Id { get; }
    string? Label { get; set; }
}

public interface ICachable : IAuxiliary
{
    int SortOrder { get; set; }
    bool IsActive { get; set; }
    bool IsDefault { get; set; }
}

public class ContractType : ICachable
{
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int ContractTypeId { get; set; }
    [NotMapped]
    public int Id { get { return ContractTypeId; } }
    [StringLength(50, MinimumLength = 3)]
    public string? Label { get; set; }
    public int SortOrder { get; set; }
    public bool IsActive { get; set; }
    public bool IsDefault { get; set; }
}

Below statement gives me all the properties of contractType, i need only Id and Label.

        var aux = from c in _appDbContext.ContractTypes
                  where c.IsActive
                  orderby c.SortOrder
                  select c as IAuxiliary;
2

There are 2 answers

0
Harald Coppoolse On

Why not use Enumerable.Cast?

IEnumerable<ContractType> contracts = ...
IEnumerable<IAuxiliary> auxiliaries = contracts.Cast<IAuxiliary>();

This is enough for most applications.

Of course it is not guaranteed that people won't cast the items back to ContractTypes. If you absolutely want to prevent that people, for instance for security reasons you don't want that people are able to inspect the other properties of ContractTypes, you'll have to create new objects that contain only properties for IAuxiliary. Be aware though, that this costs more processing power.

In the following example I use extension methods. If you are not familiar with extension methods, consider to read Extension Methods Demystified

public static IEnumerable<IAuxiliary> ToAuxiliary(this IEnumerable<ContractType> contract)
{
    // define local class that implements IAuxiliary
    class Auxiliary : IAuxiliary
    {
         public int Id => this.contractType.Id;
         public string? Label
         {
             get => this.contractType.Label;
             set => this.contractType.Label = value;
         }
    }

    // the code to create the Auxiliaries:
    if (contracts == null) throw ArgumentNullException(...);

    return contracts

        // only if you expect null contractTypes:
        .Where(contractType => contractType != null)

        // create Auxiliaries
        .Select(contractType => new Auxiliary
        {
            Id = contractType.Id,
            Label = contractType.Label,
        });
}

Usage:

IEnumerable<ContractType> contracts = ...
IEnumerable<IAuxiliary> auxiliaries = contracts.ToAuxiliaries();
0
LojiSmith On

I used below to consider all my auxiliary types as OCachable

_appDbContext.Set<ContractType>().OfType<ICachable>()

then i simply used automapper to only retrieve id and label. will consider only selecting id and label once implementation is complete.