views:

96

answers:

3

i'm creating an html.helper for a 3rd party javascript grid component. i'm passing my gridextension my viewmodel.

in my viewmodel class i've got custom attributes on my properties describing how each column is displayed.

in my gridextension, i want to then serialize my class of T. in my CreateSerializedRow method i'd like to be able to do something like row. <- and get intellisense for my class. but how to i get intellisense for the members of class T without an explicit cast?

public class GridData<T>
{
    #region Fields

    private List<Dictionary<string, object[]>> _attributes;

    private static IList<T> _dataSource;

    #endregion

    #region Properties

    public string Align { get; set; }

    public string Header { get; set; }

    public string JsonData { get; set; }

    public string Sorting { get; set; }

    public string Width { get; set; }

    #endregion

    #region Public Methods

    public void Serialize(IList<T> dataSource, List<Dictionary<string, object[]>> attributes)
    {
        _dataSource = dataSource;
        _attributes = attributes;

        JsonData = _dataSource.Count == 0 ? string.Empty : BuildJson();
    }

    #endregion

    #region Private Methods

    private static string BuildJson()
    {
        var sbJson = new StringBuilder();
        var listCount = _dataSource.Count;

        sbJson.Append("{page: 1, total:" + listCount + ", rows: [");

        for (var i = 0; i < listCount; i++)
        {
            var serialized = CreateSerializedRow(i);

            sbJson.Append(serialized);

            if (i < listCount - 1)
                sbJson.Append(",");
        }

        sbJson.Append("]}");
        return sbJson.ToString();
    }

    private static string CreateSerializedRow(int index)
    {
        var row = _dataSource[index];
        var sb = new StringBuilder();

        //sb.Append("{id:'" + Id + "',data:[");
        //sb.Append(String.Format("'{0}',", GroupName.RemoveSpecialChars()));
        //sb.Append(String.Format("'{0}',", Description));
        //sb.Append(String.Format("'{0}',", CreatedBy));
        //sb.Append(String.Format("'{0}',", CreatedDate.ToShortDateString()));
        //sb.Append(String.Format("'{0}',", EmailSubject.RemoveSpecialChars()));
        //sb.Append(String.Format("'{0}',", EmailBody));
        //sb.Append(String.Format("'{0}',", UpdatedBy));
        //sb.Append(String.Format("'{0}'", UpdatedDate.ToShortDateString()));
        //sb.Append("]}");

        return sb.ToString();
    }

    #endregion

}
+4  A: 

The best you can do is use Generic constraints, which specify that T must be castable to a specific type. See http://msdn.microsoft.com/en-us/library/ms379564%28VS.80%29.aspx#csharp%5Fgenerics%5Ftopic4 for more information.

The syntax is more or less the following:

public class MyClass<T> where T : ISomethingOrOther
{
}

At least this way, you can limit T to an interface type and code against that abstraction with Intellisense support.

David Andres
so are you saying i should wrap my different viewmodel classes in an interface and pass that interface to my gridextension?
CurlyFro
If MyClass<T> expects certain operations/properties to be present on T, then you will need this constraint present for Intellisense to work. If you want to program against the concept of a View, you can always make sure T is constrained to ViewPage or ViewPage<K> where K is a view's model type.
David Andres
A: 

If T is always a known interface or class you can do:

public class GridData<T>
    where T:MyClass
{
 ...
}
Kobi
T isn't known and shouldn't
CurlyFro
So, you can't even know it on compile time, let alone in the intellisense. On C# 4 you'll have the `dynamic` keyword, so maybe you could use overloading for that.
Kobi
+1  A: 

With what you're trying to do you'd probably have to use reflection to cycle through the properties and output the values. You might be better off making GridData an abstract class and override a method which outputs the row of data for each data class.

Or create a generic interface which has a Serialize() method that outputs a string of the objects values in the expected format. Have each model class implement this interface and then have the GridData class constrained to this interface. Assuming these are ViewModel classes, it should be a reasonable design.

Josh