0

I have a function similar to this one and i can't edit it:

internal object DoSomething(Type type, object obj)

I need to pass type as type of an ObservableCollection but T is unknown at design time.

And this is not enough:

Type t = typeof(ObservableCollection<>);

How can i solved it?

EDIT

When using LiteDb you can map POCO class properties with LiteDb objects. By default, an ObservableCollection returns an Array. I need to change this default behavior passing an ObservableCollectio and get back a BsonDocument

This code works:

BsonMapper.Global.RegisterType<ObservableCollection<Phone>>
              (serialize: (ObservableCollection) => OCToDoc(Client.Phones),
              deserialize: (BsonDocument) => new ObservableCollection<Phone>()
              );


    public BsonDocument OCToDoc<T>(ObservableCollection<T> oc)
    {           

        BsonDocument doc = new BsonDocument();
        Type t = typeof(T);
        BsonDocument item = new BsonDocument();
        doc.Add(t.Name, item);

        foreach (PropertyInfo pi in t.GetProperties())
        {
            string key = pi.Name;
            item.Add(key, new BsonValue());
        }

        return doc;
    }

RegisterType from LiteDb.dll is:

public void RegisterType<T>(Func<T, BsonValue> serialize, Func<BsonValue, T> deserialize);
public void RegisterType(Type type, Func<object, BsonValue> serialize, Func<BsonValue, object> deserialize);

I need to make a generic mapping for whichever type of ObservableCollection. This means that

ObservableCollection<Phone> 

must be

ObservableCollection<T> 

where T isn't known at runtime. So, how to pass an ObservableCollection in RegisterType<...> and in OCToDoc(...)

Noschema
  • 31
  • 6
  • What kind of type of an `ObservableCollection` do you want to send/use there when you don't know `T`? Where do you get the `ObservableCollection` from? Can't you just use `GetType()`? Please [edit] your question to include a more detailed description of what you are trying to do, what the source code is you are trying to solve and where the problems are. – Progman Nov 16 '19 at 19:26

2 Answers2

2

You need to call a method on the type to bind it to a generic parameter:

typeof(ObservableCollection<>).MakeGenericType(someType);
Artfunkel
  • 1,832
  • 17
  • 23
1

You can make the method generic

internal T DoSomething<T>(ObservableCollection<T> coll)

I made the return type T, assuming that the method will return one element of the collection. I also removed the Type type parameter, as it is replaced by the generic type parameter.

If your type is given dynamically in type, then this approach does not work.


Note that ObservableCollection<T> implements the non-generic interfaces ICollection, IList and IEnumerable. If the type is not known at design time, the best you can do, is to use one of those.

internal object DoSomething(Type type, ICollection coll)

If the method only needs to read the collection, a good approach is to use an IEnumerable<T> with T as the common base type of all your element types, assuming it is not object. Since the interface is declared as

public interface IEnumerable<out T> : System.Collections.IEnumerable

with the out keyword, it is covariant. This means, that you can supply a collection having a T' deriving from T.


Note that generics allow you to create variants of the same type at design time, but they are by no means dynamic. Since to point of generics is to give type safety, using them in dynamic scenarios (which are not type safe), they are more of a burden in dynamic scenarios.

Olivier Jacot-Descombes
  • 104,806
  • 13
  • 138
  • 188