如何正确实现通用方法?

时间:2013-02-07 20:32:21

标签: c# linq generics

有人可以帮我弄清楚如何一般地实现这个方法吗?编译器抱怨它无法解析t.Id.这是有道理的,但是,我如何告诉它所有传递的对象都将具有Id属性。这是我为T定义的接口:

namespace LiveWire.Model
{
    public interface ILiveWireModel
    {
        Guid Id { get; }
    }
}

所有存储库的接口:

internal interface ILiveWireRepository<T>
{
    ICacheProvider Cache { get; }
    string CacheKey { get; }

    SqlConnection CreateConnection();

    IEnumerable<T> GetData<TD>();

    IEnumerable<T> LoadData<TD>();

    Dictionary<Guid, T> GetCachedData<TD>();

    void ClearCache();
}

我的方法:

public IEnumerable<T> GetData<TD>()
        where TD : ILiveWireModel
    {
        var data = GetCachedData<TD>();

        if (data == null)
        {
            data = LoadData<TD>().ToDictionary(t => t.Id);

            if (data.Any())
            {
                Cache.Set(CacheKey, data, 30);
            }
        }

        return data.Values;
    }

我将整个班级都包括在内,我希望能够澄清一些事情。

internal abstract class LiveWireRepositoryBase<T> : ILiveWireRepository<T>
{
    public ICacheProvider Cache { get; private set; }
    public string CacheKey { get; private set; }

    internal LiveWireRepositoryBase()
    {
        Cache = new DefaultCacheProvider();
    }

    public SqlConnection CreateConnection()
    {
        return new SqlConnection(
            ConfigurationManager
            .ConnectionStrings["LiveWire4Database"]
            .ConnectionString);
    }

    public IEnumerable<T> GetData<TD>()
        where TD : ILiveWireModel
    {
        var data = GetCachedData<TD>();

        if (data == null)
        {
            data = LoadData<TD>().ToDictionary(t => t.Id);

            if (data.Any())
            {
                Cache.Set(CacheKey, data, 30);
            }
        }

        return data.Values;
    }

    public IEnumerable<T> LoadData<TD>()
    {
        return new List<T>();
    }

    public Dictionary<Guid, T> GetCachedData<TD>()
    {
        throw new NotImplementedException();
    }


    public void ClearCache()
    {
        throw new NotImplementedException();
    }
}

我收到了这个我不明白的错误。我尝试使用显式接口实现,但最终让我删除了我的where约束。

  

方法“LiveWire.Data.Repositories.LiveWireRepositoryBase.GetData()”的类型参数“TD”的约束必须与接口方法“LiveWire.Data.Repositories.ILiveWireRepository.GetData”的类型参数“TD”的约束匹配。 )”。请考虑使用显式接口实现。 C:\ projects \ LiveWire \ Solution \ LiveWire.Data \ Repositories \ LiveWireRepositoryBase.cs 32 31 LiveWire.Data

4 个答案:

答案 0 :(得分:1)

您可以通过将类的签名更改为

来编译此方法
public sealed class MyCache<T> where T : ILiveWireModel

(或者,如果该类位于不同的命名空间中,where T : LiveWire.Model.ILiveWireModel)。

那就是说,我不确定这个改变会解决你的问题。我只看到了你项目代码的几个片段,所以我可能错了,并且带着以下几点:

将GUID键控和整数键值保存在同一个缓存中真的是最好的设计吗?据推测,您从两个不同的来源获取数据,一个使用GUID键,另一个使用整数键。但是在将来,如果你添加第三个源,它也使用整数键怎么办?来自两个整数键源的键可能会发生冲突,并且对于某些查询,您的缓存总是错误的。就个人而言,我会维护第二个表或函数(可能保留一个整数值键的映射表,只需通过GUID值键),知道从对象到键的映射,并在需要时使用该函数检查对象是否被缓存。在剩下的所有时间里,你的缓存可以直接在键和值方面工作,而不必混淆不同类型的键。

答案 1 :(得分:0)

public IEnumerable<T> GetData<T>() where T:LiveWire.Model.ILiveWireModel { 
  //.../

}

泛型专业化。

答案 2 :(得分:0)

您需要先修改声明

public IEnumerable<T> GetData<T>()

然后,为了知道你可以使用ON T,你必须告诉它允许T是什么。

public IEnumerable<T> GetData<T>() where T : ILiveWireModel

最后,您还没有告诉我们var data实际包含的内容,GetCachedDataLoadData函数内部,您没有将T传递给我们不知道它返回什么。

我希望看到类似的东西

public IEnumerable<T> GetData<T>() where T : ILiveWireModel
{
    var data = GetCachedData<T>();

    if (data == null)
    {
        data = LoadData<T>().ToDictionary(t => t.Id);

        if (data.Any())
        {
            Cache.Set(CacheKey, data, 30);
        }
    }

    return data.Values;
}

答案 3 :(得分:0)

您在此阶段获得的异常只是说明了接口定义

IEnumerable<T> GetData<TD>();

没有为类型参数where提供相同的约束(即TD)作为实现

public IEnumerable<T> GetData<TD>() where TD : ILiveWireModel

您需要在界面中添加相同的约束。