Общее свойство в неуниверсальном классе? - PullRequest
2 голосов
/ 19 июля 2011

Я не уверен, как это сделать ...

У меня есть класс, который выполняет различные функции:

public abstract class EntityBase { ... }

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

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

Я пытаюсь получить кеш этих файлов в неуниверсальном классе:

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

Проблема в том, что EntityBase является абстрактным и не может выполнять new (), ISomeInterface ожидает класс, который основан на EntityBase и выполняет new (). Есть ли способ сделать то, что я хочу сделать?


Обновление: я понял, что для TKey я могу использовать Type, но я все еще не уверен, что поставить для ISomeInterface.

Ответы [ 3 ]

2 голосов
/ 19 июля 2011

Во-первых, я думаю, что вы хотели использовать ConcurrentDictionary, поскольку у вас есть пара ключ / значение.

Во-вторых, вы можете сделать это аналогично ICloneable.У ICloneable есть метод, который возвращает Object вместо T.

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

Так как он является частным, вы можете управлять им внутренне и приводить его по мере необходимости.Очевидно, что вам нужно убедиться, что у любых вызовов функций есть определение typeparam, например:

//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();
}

Кроме того, даже если свойство имеет другой модификатор (public, internal, protected), вы можете добавлять комментарии к вызывающимчто Object является универсальным типом ISomeInterface, где T является EntityBase, new ().Затем они просто должны привести, как им нужно.


Вы также можете иметь универсальные методы для неуниверсального класса, чтобы получить кэшированный элемент как универсальный тип:

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();
}
0 голосов
/ 19 июля 2011

Я не уверен, для чего именно вы хотите использовать эту коллекцию, но один из способов сделать что-то подобное - создать вложенный универсальный статический класс, содержащий значения:

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;
    }
}
0 голосов
/ 19 июля 2011

См. Этот связанный вопрос: Создание универсального свойства

Если вы не хотите, чтобы MyClass был универсальным, вы можете использовать вместо него два универсальных метода:

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

    private void SetCache<T>(ConcurrentCollection<T, ISomeInterface<T>> cache)
    {
        ...
    }
...