2

I'm not sure how to go about this...

I have a class that performs various functions:

public abstract class EntityBase { ... }

public interface ISomeInterface<T> where T : EntityBase, new() { ... }

public class SomeClass<T> : ISomeInterface<T> { ... }

I'm trying to have a cache of these in a non-generic class:

public class MyClass
{
    //Not sure how to do this
    private ConcurrentDictionary<?, ISomeInterface<?>> Cache { get; set; }
}

The problem is that EntityBase is abstract and can not do new(), The ISomeInterface expects a class that is based off EntityBase and does new(). Is there any way to do what I'm wanting to do?


Update: I realized that for the TKey I can use Type, but I still am not sure what to put for the ISomeInterface.

myermian
  • 31,823
  • 24
  • 123
  • 215
michael
  • 14,844
  • 28
  • 89
  • 177

3 Answers3

2

Firstly, I think you meant to use ConcurrentDictionary since you have a key/value pair.

Secondly, you can do it similar to ICloneable. ICloneable has a method that returns an Object instead of a T.

private ConcurrentDictionary<Type, Object> Cache { get; set; }

Since it's private you can manage it internally and cast it as needed. Obviously you'll have to make sure any function calls have a typeparam definition, for example:

//I omitted error checking on all the examples.
public class Foo : EntityBase { ... }

void DoSomething<Foo>()
{
    var someClass = Cache[typeof(Foo)] as ISomeInterface<Foo>
    someClass.Bar();
}

Also, even if the property had another modifier (public, internal, protected) you could add comments to callers that the Object is a generic type of ISomeInterface where T is a EntityBase, new(). Then, they simply have to cast however they need to.


You can also have generic methods on the non-generic class to get the cached item as a generic type:

ISomeInterface<T> GetInstance<T>()
    where T : EntityBase, new()
{
    return Cache[typeof(T)] as ISomeInterface<T>;
}

void AddInstance<T>(ISomeInterface<T> instance)
    where T : EntityBase, new()
{
    Cache[typeof(T)] = instance;
}

void DoSomething<T>()
{
    var someClass = GetInstance<T>();
    someClass.Bar();
}
myermian
  • 31,823
  • 24
  • 123
  • 215
0

See this related question: Making a generic property

If you don't want MyClass to be generic, you can use two generic methods instead:

    private ConcurrentCollection<T, ISomeInterface<T>> GetCache<T>()
    {
        ...
    }

    private void SetCache<T>(ConcurrentCollection<T, ISomeInterface<T>> cache)
    {
        ...
    }
Community
  • 1
  • 1
Matt Smith
  • 17,026
  • 7
  • 53
  • 103
0

I'm not sure what exactly do you want to use that collection for, but one way of doing something similar would be to create a nested generic static class that holds the values:

class SomeInterfaceCollection
{
    private static class Item<T>
    {
        public static ISomeInterface<T> Value;
    }

    public static ISomeInterface<T> Get<T>()
    {
        return Item<T>.Value;
    }

    public static void Set<T>(ISomeInterface<T> value)
    {
        Item<T>.Value = value;
    }
}
svick
  • 236,525
  • 50
  • 385
  • 514