0

Suppose I have a generic class called MyClass<T> how can I create a JavascriptConverter that will be used for any T possible (be it MyClass<OtherClass>, MyClass<SimpleClass>)?

I tried to to the following in my converter:

public Enumerable<Type> SupportedTypes
{
  get
  {
    return new List<Type>(){ typeof(MyClass<>) };
  }
}

But to no avail.

Any ideas? is this possible?
If not, is there any other way to acheive the same result?

sternr
  • 6,216
  • 9
  • 39
  • 63
  • It might be an idea explaining that you want a list of all concrete types that your generic `MyClass` could produce (are there any restrictions on `T` at all?). Then any answerers wouldn't have to look up what the `JavascriptConverter` is. – George Duckett Dec 01 '11 at 12:13
  • The problem is I don't know the list of possible T's at first. The only restrictions on T is that it's a class and has a default ctor – sternr Dec 01 '11 at 12:18

3 Answers3

0

If you are the author of the generic type, you should create an interface that your generic type inherits from. For example:

public interface IResultSet
{
    long TotalItems { get; }
    IEnumerable Items { get; }
}

public class ResultSet<T> : IResultSet, IEnumerable<T>
{
    private IEnumerable<T> _enumerable;
    private int _totalItems;

    public ResultSet(IEnumerable<T> enumerable,
                     int totalItems)
    {
        _enumerable = enumerable;
        _totalItems = totalItems;
    }

    public IEnumerable Items { get { return _enumerable; } }
    public long TotalItems { get{ return _totalItems; } }

    public IEnumerator<T> GetEnumerator()
    {
        return _enumerable.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return _enumerable.GetEnumerator();
    }
}

public class ResultSetConverter : JavaScriptConverter
{
    public override IEnumerable<Type> SupportedTypes
    {
        get
        {
            return new[] { typeof(IResultSet) };
        }
    }

    ...

    public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
    {
        if (!typeof(IResultSet).IsAssignableFrom(obj.GetType()))
        {
            return null;
        }

        var resultSet = obj as IResultSet;
        var json = new Dictionary<string, object>();

        json["totalItems"] = resultSet.TotalItems;
        json["items"] = resultSet.Items;

        return json;
    }
}
James Ross
  • 758
  • 5
  • 14
0

If you really want this, with no filters at all:

using System.Linq;

....

var concreteGenericTypes =
    (from assembly in AppDomain.CurrentDomain.GetAssemblies()
     from T in assembly.GetTypes()
     where T.IsClass && T.GetConstructor(new Type[] { }) != null
     select typeof(MyClass<>).MakeGenericType(T)).ToList();

It gets all loaded assemblies, then all types for those assemblies, then filters according to your generic where conditions, finally it makes a concrete generic type from your class and the type.

George Duckett
  • 31,770
  • 9
  • 95
  • 162
  • Using reflector on the JavaScriptSerializer, I now know there's no other way, such a shame... I wonder if this was a by-design choice, and if so why... – sternr Dec 01 '11 at 13:19
-1

As far as I can think of, as javascript is loosely typed, so having something as generic parameters is not a concern.
You can try and test using instanceof, though. check this question:
What is the instanceof operator in JavaScript?
It does what you need, at least the checking type part.

Community
  • 1
  • 1
marcelo-ferraz
  • 3,147
  • 4
  • 38
  • 55
  • MyClass instances require special (json)serialization, hence the need to create a custom serializes. this isn't directly related to javascript's loosely typed behavior... – sternr Dec 01 '11 at 12:20