deostroll
deostroll

Reputation: 11995

deferred iteration of IEnumerable<T>?

Trying to build a asp.net mvc html helper for creating a bootstrap table. I've defined my fluent interface as follows:

public interface IBootstrapObject: IHtmlString
{
    IBootstrapObject Name(string name);
    IBootstrapObject AddClass(params string[] classNames);
    //IBootstrapObject RemoveClass(params string[] classNames);
}

So the implementing class now has to have a ToHtmlString() definition. The underlying data that this table helper would bind to could be something like a List<Person> (assume Person it has standard properties here like FirstName, LastName, etc).

Hence say I've defined the following:

public class BootstrapTable : IBootstrapObject
{
    IEnumerable _dataSet;
    public IBootstrapObject DataSet<T>(IEnumerable<T> dataSet)
    {
        _modelType = typeof(T);
        _dataset = dataSet;
        return this;
    }

    public string ToHtmlString()
    {

    }

    //remaining code ...
}

How to access the IEnumerable<T> passed during in the DataSet<T>() inside of ToHtmlString() ?

In one sense, I know this involves caching it somewhere, and re-accessing it inside ToHtmlString(). And that is why I used _dataSet. How to convert that IEnumerable to the generic IEnumerable<T>?

Upvotes: 0

Views: 89

Answers (1)

Jon Skeet
Jon Skeet

Reputation: 1502336

You don't need to access it as an IEnumerable<T>. You can just use the non-generic IEnumerable:

var properties = _modelType.GetProperties(); // Or whatever... remove indexers etc
foreach (object item in _dataSet)
{
    foreach (var property in properties)
    {
        var value = property.GetValue(item, null);
        // Use the value somehow
    }
}

If you really want to have it as an IEnumerable<T>, and you don't want the type itself to be generic, then you'll need a generic method, which you can then call by reflection or using dynamic typing to do the heavy lifting:

public string ToHtmlString()
{
    dynamic data = _dataSet;
    ToHtmlString(data);
}

private string ToHtmlString<T>(IEnumerable<T> data)
{
    ...
}

Note that using dynamic typing like this, T may not be the same T as in the original method. An alternative using reflection:

public string ToHtmlString()
{
    var method = typeof(BootstrapTable).GetMethod("ToHtmlStringImpl",
        BindingFlags.Instance | BindingFlags.NonPublic);
    var concreteMethod = method.MakeGenericMethod(_modelType);
    concreteMethod.Invoke(this, new object[] { _dataSet });
}

private string ToHtmlStringImpl<T>(IEnumerable<T> data)
{
    ...
}

Upvotes: 2

Related Questions