简体   繁体   中英

Iterate over generic list with multiple types

I have 3 classes as mentioned below: One has the information for removal, rest two classes have actual data. In future there will be more than 30 classes for data

public class RemovalInformation<T> where T:class
{
    public string TagName { get; set; }
    public T Data { get; set; }
    public Func<T, bool> RemovalCondition { get; set; }
}

public class PropertyReportData
{
    public string PropertyName { get; set; }
}

public class ValuationData
{
    public DateTime ValuationDate { get; set; }
}

I have a below ArrayList which I want to process

        var removals = new ArrayList
        {
            new RemovalInformation<PropertyReportData>
            {
                Data = commercialReportData?.PropertyDetail,
                TagName = nameof(PropertyReportData.PropertyName),
                RemovalCondition = property => string.IsNullOrWhiteSpace(property.PropertyName),
            },
             new RemovalInformation<ValuationData>
            {
                Data = commercialReportData?.ValuationData,
                TagName = nameof(ValuationData.ValuationDate),
                RemovalCondition = property => property.ValuationDate< DateTime.Today,
            }
        };

        ProcessRemovals(removals);

Method ProcessRemovals is

    private void ProcessRemovals(ArrayList removals)
    {
        foreach (RemovalInformation<PropertyReportData> item in removals)
        {
            var deleteItem = item.RemovalCondition.Invoke(item.Data);
            if (deleteItem)
            {
               //do something here
            }
        }
    }

The problem here is, in foreach loop I can access RemovalInformation of only one type. Is there any way to iterate over the list for multiple types of RemovalInformation

You could use an interface, something like this:

public interface IProcessRemoval
{
   bool Execute();
}

Just implement it:

public class RemovalInformation<T> : IProcessRemoval where T:class
{
    public string TagName { get; set; }
    public T Data { get; set; }
    public Func<T, bool> RemovalCondition { get; set; }
    public bool Execute()
    {
        if (RemovalCondition != null) 
        {
            return RemovalCondition(Data);
        }
        return false;
    }
}

Then iterate:

private void ProcessRemovals(ArrayList removals)
{
    foreach (IProcessRemoval item in removals)
    {
        var deleteItem = item.Execute();
        if (deleteItem)
        {
           //do something here
        }
    }
}

As answered by @mtanksl, in order to be able to access to common properties/methods that all the types shares, you will have to define an interface (or abstract class). but for the specific types you can use c# 7(and above) pattern matching:

private static void ProcessRemovals(ArrayList removals)
{
    foreach (var r in removals)
    {
         switch(r)
         {
             case RemovalInformation<PropertyReportData> propertyReportData:
                 //do delete with propertyReportData
                 break;
             case RemovalInformation<ValuationData> valuationData:
                 //do delete with valuationData
                 break;
             default:
                 var removalInfo = (IRemovalInformation)r;
                 //do delete with removalInfo that should holds all the common properties and methods
                 break;
         }

    }
}

You can alternatively use dynamic type:

private void ProcessRemovals(ArrayList removals)
{
    foreach (dynamic item in removals)
    {
        var deleteItem = item.RemovalCondition.Invoke(item.Data);
        if (deleteItem)
        {
           //do something here
        }
    }
}

Add using System.Linq; at the start of the file and apply .OfType<T>() to filter only a certain type of items in the collection (where T is the type you need):

foreach (RemovalInformation<PropertyReportData> item in removals.OfType<RemovalInformation<PropertyReportData>>())
{    
    //do something here
}

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