开发者

C# Can I create a generic method or property inside a non-generic class that returns a different generic class?

I have a abstract generic class. I w开发者_JS百科ant to define a method inside there so I won't have to do it in all derived classes.

Basically I need to fetch a repository class based on the Type the generic class will be.

I fetch the repoistories through another class which is non generic.

How can I let that class return a generic repository based on the type the generic caller has?

I was hoping for something like this.

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

If it would be a property it will be even better.


C# has no way to express the "self" type, but you can emulate it with the curiously recurring template pattern (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> {  }

Usage:

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

This isn't fool-proof though. For more details, read this blog post by Eric Lippert: Curiouser and curiouser.


On the other hand, if you only need the type argument for the _container.Resolve call to be based on the current-type, but can return a more general type from the method, you don't have to resort to this pattern. You can use reflection instead:

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


I don't see the problem. You could write code like this that compiled. Does this not accomplish what you want?

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜