Search code examples
c#design-patternscompositeenumerable

C# composite pattern : Program.IAsset is not enumerable


Hi I am trying to create a directory structure using composite pattern. I have an interface IAsset which is implemented by the file and folder class. So both are an Asset. Now I want to loop through all the files in all the folders but I am getting the error message:

Program.IAsset is not enumerable

This error message is in the inner foreach loop of getassetSize() method.

public class Program { public interface IAsset { double GetAssetSize(); void AddAsset(IAsset a); }

public class File : IAsset
{
    public double Size { get; set; }
    public double GetAssetSize()
    {
        return Size;
    }

    public void AddAsset(IAsset a)
    {
        Console.WriteLine("No asset can be added to a file");

    }
}

public class Folder : IAsset
{
    public double Size { get { return _size; } set { _size = value; } }

    private double _size = 0;

    public List<IAsset> list = new List<IAsset>();

    public double GetAssetSize()
    {
        foreach (var asset in list)
        {
            foreach (var x in asset)
            {
            //    _size = x.GetAssetSize();
            }

        }
        return _size;
    }

    public void AddAsset(IAsset a)
    {
        list.Add(a);
    }
}

Solution

  • To fit into the composite pattern IAsset would need to inherit IEnumerable<IAsset> or provide a member which implements it. For example:

    public interface IAsset : IEnumerable<IAsset>
    { 
        double GetAssetSize(); 
        void AddAsset(IAsset a); 
    }
    
    public class File : IAsset
    {
        ...
        public IEnumerator<IAsset> GetEnumerator()
        {
            return new IAsset[0].GetEnumerator();
        }
    
        IEnumerator IEnumerable.GetEnumerator()
        {
            return this.GetEnumerator();
        }
    }
    
    public class Folder : IAsset
    {
        ...
        public IEnumerator<IAsset> GetEnumerator()
        {
            return this.list.GetEnumerator();
        }
    
        IEnumerator IEnumerable.GetEnumerator()
        {
            return this.GetEnumerator();
        }
    }
    

    Or this:

    public interface IAsset
    { 
        double GetAssetSize(); 
        void AddAsset(IAsset a); 
        IEnumerable<IAsset> Assets { get; }
    }
    
    public class File : IAsset
    {
        ...
        public IEnumerator<IAsset> Assets 
        {
            get { return new IAsset[0]; }
        }
    }
    
    public class Folder : IAsset
    {
        ...
        public IEnumerator<IAsset> GetEnumerator()
        {
            get { return this.list; }
        }
    }