首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Shim和泛型方法

Shim和泛型方法
EN

Stack Overflow用户
提问于 2015-03-17 07:58:20
回答 1查看 1.3K关注 0票数 3

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

以下是我的例子:

代码语言:javascript
复制
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
{
}

现在我想为ClassA和ClassB创建一个ClassB

代码语言:javascript
复制
ShimBaseRepository<A>.AllInstances.FindAll = (repo) => MethodA();
ShimBaseRepository<B>.AllInstances.FindAll = (repo) => MethodB();

public A MethodA()
{
    //Make the Same as MethodB
}

public B MethodB()
{
    //Make the Same as MethodA
}

但是如果我有超过20个“基本”类呢?我不想为每个baseClass创建一个委托/方法。我试过这样的方法:

代码语言:javascript
复制
List<Type> allEntityClasses = (from x in Assembly.GetAssembly(typeof(Entity)).GetTypes()
                                    where !x.IsAbstract && !x.IsInterface
                                    select x).ToList();

foreach(Type type in allEntityClasses=
{
    ShimBaseRepository<type????>.AllInstances.FindAll = (repo) => Method();
}

public Entity????? Method()
{
}

在我的Unittest中,我将使用以下方法:

代码语言:javascript
复制
ClassA.FindAll()
ClassB.FindAll()

而不是:

代码语言:javascript
复制
Base.FindAll()

编辑:我使用微软的赝品,所以我不能改变ShimClass中的任何东西。下面是从Shim生成的源代码。

代码语言:javascript
复制
  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; }
    }
  }

我的意图是,我不想为每个实体创建一个委托,我只想遍历我的所有EntityClasses并动态创建委托。但是我不知道如何将Type对象添加到

代码语言:javascript
复制
ShimBase<T>
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-03-17 08:58:55

好吧,让我们讨论一下。首先,这里有一个使用虚拟方法的直进解决方案:

代码语言:javascript
复制
public class Base<T> where T : Entity
{
    public virtual T[] FindAll()
    {
        return null;
    }
}

然后,只需在具体的类中重写FindAll,或者,如果可以的话,也可以将Base抽象和InnerFindAll抽象。

但是,如果您需要在运行时指定委托(正如我所看到的那样,您有一个特定的帮助程序,但我无法得到,为什么在Base中调用助手,然后使用一个Func函数在问题AllInstances中有一些未定义的),这种方法不会有帮助。您需要使用在Base中分配的默认策略来实现战略模式。然后,在具体的类中有3种“解决”策略的方法:

  1. 具体类构造函数中的硬编码策略
  2. 通过DI容器向具体类构造函数注入策略
  3. 实现某种映射器,它将为EntityType (T)返回合适的策略

另外,我认为你在设计上有一些问题。我不认为您需要将FindAll实现为注入Func<T>类型的静态属性的lambda (是的,我认为您可以用一个static FindAll代替AllInstances.FindAll )。所以如果我是你,我会用抽象的方法。

编辑

现在我知道你的问题了,只能通过反思给你一个很难看的解决方案.我不建议你用这个,因为它真的很严格

代码语言:javascript
复制
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
{

}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29093896

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档