There are problems with Generics in this .NET code.

I am trying to create a mixed collection of types. I know types from the very beginning .. but I can't figure out how syntax to make a collection, etc.

eg.

....
// I leave the typo there, for embarrassment :(
Initialize(new []{ typeof(Cat), typeof(Dog), typeof(JohnSkeet) }); 
...

public Foo Initialize(IEnumerable<Type> types)
{
   // for each type, set up the inmemory storage.
   foreach(var type in types)
   {
       // ????
       // Create an empty list, which will only contain this 'type'
       // I'm guessing, an IDictionary<type, ICollection<type>>().. thingy ?
   }
}

public ICollection<Type> SomeTypeData(Type type)
{
    // Return the collection, for this type.
}

Does this feeling? Is it possible?

+3
source share
4 answers

It seems to me that you are trying to create some kind of instance repository; the class that stores the list of instances of a particular type.

Here is an example implementation. I have included both a generic and a non-generic version of the SomeTypeData method:

public class InstanceRepository
{
    private IDictionary<Type, ICollection> _Instances = new Dictionary<Type, ICollection>();

    public ICollection SomeTypeData(Type type)
    {
        ICollection instanceList;
        if (!_Instances.TryGetValue(type, out instanceList))
        {
            // this type does not exist in our dictionary, so let create a new empty list

            // we could do this:
            //instanceList = new List<object>();

            // but let use reflection to make a more type-specific List<T> instance:
            instanceList = (ICollection)Activator.CreateInstance(typeof(List<>).MakeGenericType(type));

            // now add it to the dictionary
            _Instances.Add(type, instanceList);
        }
        // Return the collection, for this type.
        return instanceList;
    }

    public IList<T> SomeTypeData<T>()
    {
        Type type = typeof(T);
        ICollection instanceList;
        if (!_Instances.TryGetValue(typeof(T), out instanceList))
        {
            instanceList = new List<T>();
            _Instances.Add(type, instanceList);
        }
        // here we are assuming that all of the lists in our dictionary implement IList<T>.
        // This is a pretty safe assumption, since the dictionary is private and we know that
        // this class always creates List<T> objects to put into the dictionary.
        return (IList<T>)instanceList;
    }
}

The following is an example of use:

Generic:

        InstanceRepository repository = new InstanceRepository();

        var listOfCats = repository.SomeTypeData<Cat>();

        listOfCats.Add(new Cat());

        Cat firstCat = listOfCats[0];

        Console.WriteLine(listOfCats.GetType().FullName);

not common:

        InstanceRepository repository = new InstanceRepository();

        var listOfCats = (IList<Cat>)repository.SomeTypeData(typeof(Cat));

        listOfCats.Add(new Cat());

        Cat firstCat = listOfCats[0];

        Console.WriteLine(listOfCats.GetType().FullName);
+1
source

Ok, now that I think I know what you want, it would look something like this:

// This can't really be *properly* statically typed
private readonly Dictionary<Type, object> typeMap = new 
    Dictionary<Type, object>();

public Foo Initialize(IEnumerable<Type> types)
{
   Type genericListType = typeof(List<>);
   foreach(var type in types)
   {
       // MakeGenericType is really badly named
       Type constructedListType = genericListType.MakeGenericType(type);
       typeMap[type] = Activator.CreateInstance(constructedListType);
   }
}

// We can't express this particularly safely either,
// although we *could* return the non-generic IList
public object SomeTypeData(Type type)
{
    return typeMap[type];
}

// This *is* statically typed, although we need to cast inside
public IList<T> SomeTypeData<T>()
{
    return (IList<T>) typeMap[typeof(T)];
}

. .

, -, , ... SomeTypeData ... , .

+6

, , , IEnumerable<Type>, , - (, List<Type>)?

    public ICollection<Type> Initialize(IEnumerable<Type> types)
    {
        ICollection<Type> collection = new List<Type>(types);

        return collection;
    }
0

, -

_dict[typeof(Cat)]=new List<Cat>();
_dict[typeof(Dog)]=new List<Dog>();

?

- :

public void Initialize(IEnumerable<Type> types)
{
    foreach(var type in types)
    {
        var list = Activator.CreateInstance(Type.GetType("System.Collections.Generic.List`1").MakeGenericType(type));
        _cache[type] = list;
    }
}

public ICollection<T> Get<T>()
{
    object list;
    if (_cache.TryGetValue(typeof(T), out list)
    {
       return list as ICollection<T>;
    }
    else
    {
       ...
    }
}

var cats = Get<Cat>();
0

Source: https://habr.com/ru/post/1765296/


All Articles