非泛型类中的泛型属性

本文关键字:泛型 属性 泛型类 | 更新日期: 2023-09-27 18:02:22

我不知道该怎么做……

我有一个执行各种功能的类:

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放什么。

非泛型类中的泛型属性

首先,我认为你的意思是使用ConcurrentDictionary,因为你有一个键/值对。

其次,你可以像iclonable那样做。iclonable有一个返回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();
}

参见相关问题:创建通用属性

如果你不希望MyClass是泛型的,你可以使用两个泛型方法:

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

我不确定您究竟想要使用该集合做什么,但做类似事情的一种方法是创建一个嵌套的通用静态类,其中包含值:

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;
    }
}