C# 垫片和通用方法

C# 垫片和通用方法,c#,generics,shim,C#,Generics,Shim,我想为泛型方法创建一个垫片。但在这种情况下,我对通用型有点麻烦 以下是我的例子: class BaseRepository <T> where T: Entity { public T[] FindAll() { return Method<T>.FindAll() } } class ClassA : base<A> { } class A : Entity { } class ClassB : base<

我想为泛型方法创建一个垫片。但在这种情况下,我对通用型有点麻烦

以下是我的例子:

class BaseRepository <T> where T: Entity
{
    public T[] FindAll()
    {
        return Method<T>.FindAll()
    }
}

class ClassA : base<A>
{
}

class A : Entity
{
}

class ClassB : base<B>
{
}

class B : Entity
{
}
而不是:

Base.FindAll()
编辑: 我使用Microsoft Fakes,因此无法更改ShimClass中的任何内容。以下是从Shim生成的源代码

  public class ShimBaseRepository<T> : ShimBase<BaseRepository<T>> where T : Entity
  {
    public static class AllInstances
    {
        public static FakesDelegates.Func<BaseRepository<T>, T[]> FindAll { [ShimMethod("FindAll", 20)] set; }
    }
  }
公共类ShimBaseRepository:ShimBase其中T:Entity
{
公共静态类AllInstances
{
公共静态FakesDelegates.Func FindAll{[ShimMethod(“FindAll”,20)]集;}
}
}
我的意图是,我不想为每个实体创建一个委托,我只想遍历我所有的EntityClass并动态创建委托。但我不知道如何将类型对象添加到

ShimBase<T>
ShimBase

好的,让我们稍微讨论一下。 首先,这里是一个采用虚拟方法的直截了当的解决方案:

public class Base<T> where T : Entity
{
    public virtual T[] FindAll()
    {
        return null;
    }
}

你想解决的问题是什么?你向我们展示的是一个不起作用的解决方案,但不是你实际遇到的问题。另外,请确保您确实有可以运行的示例代码。我使用Microsoft.Fakes进行测试,但不编写这些类。我只是想用它。我添加了从microsoft fakes生成的源代码。这也是我第一次使用microsoft fakes,这就是我出现问题的原因。我有我的BaseRepository,其中T:Entity从接口获取一些数据。现在我写了一些单元测试,我不想/不能通过这个接口。所以我“伪造”了这个接口并重写了BaseRepository方法。使用ShimBase.AllInstances.FindAll=(repo)=>Method();我调用testmethod而不是Interfacemethod。现在我必须为每个EntityClass创建一个委托,或者程序尝试通过接口。但是有大约100个EntityClass…@wydy我更新了我的答案,请告诉我这是否有用。它经常使用反射,所以我觉得它非常难看而且不可维护
  public class ShimBaseRepository<T> : ShimBase<BaseRepository<T>> where T : Entity
  {
    public static class AllInstances
    {
        public static FakesDelegates.Func<BaseRepository<T>, T[]> FindAll { [ShimMethod("FindAll", 20)] set; }
    }
  }
ShimBase<T>
public class Base<T> where T : Entity
{
    public virtual T[] FindAll()
    {
        return null;
    }
}
public class Program
{
    static void Main(string[] args)
    {
        List<Type> allEntityClasses = (from x in Assembly.GetAssembly(typeof(Entity))
                                           .GetTypes().Where(t=>typeof(Entity).IsAssignableFrom(t))
                                       where !x.IsAbstract && !x.IsInterface
                                       select x).ToList();
        foreach (var type in allEntityClasses)
        {
            var genericType = typeof(BaseGeneric<>).MakeGenericType(type);
            var helper = new DelegateHelper();
            var myLambda = helper.GetLambdaForType(type);
            var allInst = genericType.GetProperty("AllInstances").GetValue(null);
            if (allInst == null)
            {
                allInst = Activator.CreateInstance(genericType.GetProperty("AllInstances").PropertyType);
            }
            allInst.GetType().GetProperty("FindAll").SetValue(allInst,myLambda);
        }
    }


}

public static class BaseGeneric<T>
{
    public static AllInstances<T> AllInstances { get; set; }
}

public class AllInstances<T>
{
    public Func<T[]> FindAll { get; set; }
}

public class DelegateHelper
{
    public Delegate GetLambdaForType(Type type)
    {
        var funcType = typeof(Func<>).MakeGenericType(type.MakeArrayType());
        var methodInfo = typeof(DelegateHelper).GetMethods().FirstOrDefault(t => t.Name == "FunctionMethod")
                                               .MakeGenericMethod(type);
        var @delegate = methodInfo.CreateDelegate(funcType, this);
        return @delegate;
    }

    public T[] FunctionMethod<T>()
    {   
        return new T[10];
    }
}

public  class Entity
{
}

public class EntityFirst
{

}

public class EntitySecond
{

}