键入Agnostic类来调用泛型类中的泛型和非泛型方法?

时间:2011-05-25 23:15:33

标签: c# asp.net generics

我有以下课程:

public class GenericClass<T> : IGenericClass<T> where T : class
{
    public GenericClass()

    public GenericClass(Entity e)

    public IQueryable<T> GenericMethod1()

    public IEnumerable<T> GenericMethod2()

    public T NonGenericMethod1(T t)
}

班级很有效;但是我开始遇到一些问题,我必须为我想要使用的每种类型T实例化另一个GenericClass实例,而且它有点疯狂。我可以创建一些抽象来简化这个吗?

我正朝这个方向前进,但我不知道这是否是正确的选择,或者是否有更好的设计模式我可以使用;此外,两个调用调用根本无法正常工作。

public class TestClass
{
    private Type type;

    public object Invoke(string method, object obj)
    {
        type = obj.GetType();

        MethodInfo m = typeof(GenericClass<>).GetMethod(method);

        var result = new object();

        if(m.IsGenericMethod == true)
            result = m.MakeGenericMethod(type).Invoke(null, new object[] { obj });
        else
            result = m.Invoke(null, new object[] { obj });

        return result;
    }
}

TIA

2 个答案:

答案 0 :(得分:2)

  然而,我开始遇到一些问题,我必须为我想要使用的每个类型T实例化另一个GenericClass实例,而且它有点疯狂

如果没有GenericClass的一些实现,很难猜测......但我看到构造函数和方法 - 没有属性(没有字段?)。

如果是这种情况,您可能希望使用静态方法使GenericClass成为静态类。然后你不允许实例化它,你可以直接从类型调用方法:

public static class GenericClass
{
  public static IQueryable<T> GenericMethod1<T>() where T:class

  public static IEnumerable<T> GenericMethod2<T>() where T:class

  public static object NonGenericMethod1(object t)
}

调用
IQueryable<Customer> query = GenericClass.GenericMethod1<Customer>();
IEnumerable<Customer> items = GenericClass.GenericMethod2<Customer>();
Customer c = (Customer) GenericClass.NonGenericMethod1(customerInstance);

或许有属性或字段,但它们不依赖于T,那么您可以将Generic责任移到方法而不是类。

现在你可以拥有一个实例,并且该实例可以处理你想要抛出的所有T。

public class GenericClass : IGenericClass
{
  public IQueryable<T> GenericMethod1<T>() where T:class

  public IEnumerable<T> GenericMethod2<T>() where T:class

  public object NonGenericMethod1(object t)
}

我为这个答案的通用性道歉,但这是由于问题的一般性问题。

答案 1 :(得分:1)

我不认为这种方法会起作用。主要问题是您正在尝试基于类型创建泛型方法,以避免实例化相应GenericClass<T>的实例。但是Invoke失败的原因是你传递null作为目标对象,即使它们是实例方法。让它们工作的方法是构造适当的GenericClass<T>的实例,但当然这是你想要避免的。

如果你想要这条反射路线(所以你仍然有集中的建筑位置),你可以通过以下代码反射来做到这一点:

Type specificType = typeof(GenericClass<>).MakeGenericType(new Type[] { type });
var specificInstance = Activator.CreateInstance(specificType);

然后,您可以将specificInstance作为第一个参数传递给Invoke()