簡體   English   中英

在 C# 中從其接口的泛型類型存儲和訪問類的實現特定數據

[英]storing and accessing implementation specific data of a class from generic type of its interface in c#

我正在嘗試編寫一個通用緩存存儲庫,為正在緩存的每個數據類型添加一個基本鍵。

    public interface ICacheModel
    {
        private static readonly string _baseKey;
        public static string GetBaseCacheKey()
        {
            return _baseKey;
        }
    }
    public interface ICacheRepository<T> where T : class, ICacheModel
    {
        Task<T> GetAsync(string key);
    }
    public class CacheRepository<T> : ICacheRepository<T> where T : class, ICacheModel
    {
        private readonly IDistributedCache _distributedCache;

        public CacheRepository(IDistributedCache distributedCache)
        {
            _distributedCache = distributedCache;
        }

        public async Task<T> GetAsync(string key)
        {
            var res = await _distributedCache.GetAsync<T>(T.GetBaseCacheKey() + key );
            return res;
        }
    }

然后我繼承我計划從 ICacheModel 緩存的任何對象,並在我需要在我的項目中緩存的任何地方注入 ICacheRepository。

但由於編譯器錯誤 CS0119,我無法訪問靜態方法GetBaseCacheKey()

關於如何擁有此功能的任何想法?

更新:


    public class CacheSampleClass : ICacheModel
    {
        public Guid Id { get; set; }
        public string Prop1 { get; set; }
        public string Prop2 { get; set; }

        private static readonly string _baseKey = "CacheSampleClass-";
        public static string GetBaseCacheKey()
        {
            return _baseKey;
        }
    }

這是我要緩存的繼承類的示例。 我希望 GetBaseCacheKey 在由 CacheSampleClass 制作的所有對象中是唯一的,並且與由繼承 ICacheModel 的其他類制作的所有對象不同

最簡單的解決方案可能是使用反射來獲取類名作為“baseCacheKey”。

_distributedCache.GetAsync<T>(typeof(T).FullName  + key );

另一種解決方案是將基本鍵定義為緩存對象的參數,而不是類型:

public CacheRepository(IDistributedCache distributedCache, string baseKey) 
...

第三種解決方案是在接口中定義一個屬性:

public interface ICacheModel
{
        public string BaseKey {get;}
}

所述接口的實現可以只提供返回常量或文字值的 get 方法的實現,因此沒有任何針對每個對象的字段。 但是該屬性不能像發布的示例中那樣是靜態的。

每種選擇都有一些優點和缺點,因此這取決於您想要做什么。

接口中的靜態成員是在 C# 8.0 中引入的,我建議您避免使用它們,因為接口通常應該將實現(字段)與合同(方法或屬性)斷開連接。

在您的情況下,最好轉換為常規財產

public interface ICacheModel
{
   string GetBaseCacheKey();
}

並將使用靜態字段的實現移動到實現您的接口的類

不能實現靜態接口方法; 靜態成員只屬於它們的聲明類型。

你可以這樣做:

public interface ICacheModelKeyProvider<T> where T : class
{
    string BaseKey { get; }
}

然后在您的存儲庫中:

public class CacheRepository<T> : ICacheRepository<T> where T : class
{
    private readonly IDistributedCache distributedCache;
    private readonly ICacheModelKeyProvider<T> keyProvider;

    public CacheRepository(
        IDistributedCache distributedCache,
        ICacheModelKeyProvider<T> keyProvider)
    {
        this.distributedCache = distributedCache;
        this.keyProvider = keyProvider;
    }

    public async Task<T> GetAsync(string key)
    {
        var res = await _distributedCache.GetAsync<T>(keyProvider.BaseKey + key);
        return res;
    }
}

然后,您創建的每個模型類型都需要一個ICacheModelKeyProvider然后才能擁有存儲庫。

例如

public class CacheSampleClass
{
    public Guid Id { get; set; }
    public string Prop1 { get; set; }
    public string Prop2 { get; set; }
}

public class CacheSampleClassKeyProvider : ICacheModelKeyProvider<CacheSampleClass>
{
    public string BaseKey { get; } = "CacheSampleClass-"; 
}

或者,如果您想要默認行為,您甚至可以擁有一個通用提供程序:

public class DefaultKeyProvider<T> : ICacheModelKeyProvider<T>
{
    public string BaseKey { get; } = $"{typeof(T).Name}-"; 
}

如果感覺更整潔,您甚至可以嵌套該類:

public class CacheSampleClass
{
    public Guid Id { get; set; }
    public string Prop1 { get; set; }
    public string Prop2 { get; set; }

    public class KeyProvider : DefaultKeyProvider<CacheSampleClass> { }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM