C#我可以在返回不同泛型类的非泛型类中创建泛型方法或属性吗?

时间:2011-02-21 14:18:26

标签: c# generics methods properties

我有一个抽象的泛型类。我想在那里定义一个方法,所以我不必在所有派生类中都这样做。

基本上我需要根据泛型类的类型获取一个存储库类。

我通过另一个非通用的类来获取repoistories。

如何让该类根据通用调用者的类型返回通用存储库?

我希望有这样的事情。

public IRepository<T> Table<T>()
{
    return _container.Resolve<IRepository<T>>();
}

如果它是一个财产,它会更好。

2 个答案:

答案 0 :(得分:6)

C#无法表达“自我”类型,但您可以使用奇怪的重复模板模式(CRTP)模拟

public class Base<TSelf> where TSelf : Base<TSelf> 
{
    // Make this a property if you want.
    public IRepository<TSelf> GetTable()
    {                   
        return _container.Resolve<IRepository<TSelf>>();          
    }
}

public class Derived : Base<Derived> {  }

用法:

IRepository<Derived> table = new Derived().GetTable();  

但这不是万无一失的。有关更多详细信息,请阅读Eric Lippert撰写的这篇博客文章:Curiouser and curiouser


另一方面,如果您只需要_container.Resolve调用的类型参数基于当前类型,但可以从该方法返回更通用的类型,则不必诉诸这种模式。您可以改为使用反射:

// If the container's Resolve method had an overload that 
// accepted a System.Type, it would be even easier.
public SomeBaseType GetTable()
{
   var repositoryType = typeof(IRepository<>).MakeGenericType(GetType());

   var result = _container.GetType()
                          .GetMethod("Resolve")
                          .MakeGenericMethod(repositoryType)
                          .Invoke(_container, null);

   return (SomeBaseType) result;     
}

答案 1 :(得分:1)

我没有看到问题。你可以编写这样编译的代码。这不能达到你想要的效果吗?

interface IRepository<T>
{
    T GetData();
}

class Container
{
    private object[] data = null;

    public T Resolve<T>()
    {
        return(T)data.First(t => t.GetType() is T);
    }
}

abstract class Handler<T>
{
    private Container _container;

    public IRepository<T> Table
    {
        get
        {
            return _container.Resolve<IRepository<T>>();
        }
    }
}