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>>();
}
}
}
精彩评论