This project has moved. For the latest updates, please go here.
1
Vote

Add support for interfaces

description

[From email]
While I was experimenting with the DynamicComparer<T> class, I noticed that it works beautifully where T is a class. When I tried to use an interface for T instead of a class, I get an exception on line 62 of DynamicComparer.cs.

My thought is that the interface describes what a class must support, so why wouldn't an interface work just as well? Though, I'm not sure how the interface would affect code generation...should it?

Let me give you an example to help highlight. The example works with a file system (files and folders). In short, I want to optimally layout, using the minimum number of media (CD, DVD), all files and folders the user has selected. For me, even the size of folders is just as important as file size -- hence the abstraction to IItem (see below). Note: Your class works even in .NET 3.5!! The example is a little longer than I had hoped, but I think it conveys the purpose in the Main() method right up front. Everything below that is just support.

static class Program
{
static void Main()
{
    DirectoryInfo dir = new DirectoryInfo( @"C:\Users\Rob\Documents\Projects" );
    FolderItem compilation = new FolderItem( dir );   // recursively builds a list of files and subfolders

    // get ready for Bin Packing problem
    List<IItem> list = new List<IItem>();
    AddCompilationToList( list, compilation );    // I do not show an implementation for this method as it is trivial

    // Of course, the UI may just want to sort by Size or by Name or by Location
    // But, this is what I'd like to do to sort files AND folders by their size (descending), then location, then name
    //    This sort is needed when implementing the Bin Packing algorithm using First, Worst, or Best Item approaches
    DynamicComparer<IItem> comparer = new DynamicComparer<IItem>( "Size DESC, Location, Name" );
    list.Sort( comparer.Comparer );

    // now do one of the Bin Packing algorithms -- not shown for space
}
}

interface IItem : IComparable<IItem>, IEquatable<IItem>
{
IContainerItem Parent { get; }
string Name { get; }
string Location { get; }
long Size { get; }
}

interface IContainerItem : IItem
{
ItemCollection Items { get; }
IEnumerable<FileItem> Files { get; }
IEnumerable<IContainerItem> Folders { get; }
}

class FileItem : IItem
{
FileInfo _file;

public FileItem( FileInfo file )
{
    _file = file;
}

public string Name
{
    get { return _file.Name; }
}

public string Location
{
    get { return _file.DirectoryName; }
}

public long Size
{
    get { return _file.Length; }
}
}

class FolderItem : IContainerItem
{
DirectoryInfo _dir;
long _size;

public FolderItem( DirectoryInfo dir )
{
    _dir = dir;
    BuildTree();
}

public string Name
{
    get { return _dir.Name; }
}

public string Location
{
    get { return _dir.FullName; }
}

public long Size
{
    get { return _size; }
}

public ItemCollection Items
{
    get { return _items; }
}

public IEnumerable<FileItem> Files
{
    // Use LINQ to pull out only file from the ItemCollection
    get { return (from item in Items where item is FileItem select item as FileItem).AsEnumerable<FileItem>(); }
}

public IEnumerable<IContainerItem> Folders
{
    // Use LINQ to pull out only folders (containers) from the ItemCollection
    // I have other types of IContainerItems which is why I don't return FolderItem
    get { return  ( from item in Items 
                        where item is IContainerItem 
                        select item as IContainerItem).AsEnumerable<IContainerItem>(); }
}

private void BuildTree()
{
    // use dir.GetFiles() and dir.GetDirectories() and convert each to FileItem and FolderItem respectively
    // recursively drill down each folder in dir.GetDirectories()
}

comments