2

我有一个通用函数,它将接口作为一种类型,现在在一种情况下,我必须根据接口创建一个新类。我一直在考虑它,解决它的一种方法是使用 IoC,但我希望有另一种方法,因为 IoC 似乎有点矫枉过正。

下面是使用访问者模式的尝试:

public class RepositoryManager<T> : IRepositoryManager<T> where T : class, new()
{
    public T GetOrCreate(string id)
    {
        T item = (T)CreateNew(new T(), id);
        return item;
    }
}

如果我得到一个对象而不是接口,那么我可以使用访问者模式来确定要实例化的类,但根据提供的接口,我似乎无法弄清楚这一点。

我的另一个想法是,我是否可以像 or 一样做出 where 声明?

public class RepositoryManager<T> : IRepositoryManager<T> where T : class, Iabc or Ixyz, new()

我希望问题很清楚:)

-标记


谢谢你的回复。

问题是该方法可以分配有许多不同的接口,例如:

RepositoryManager 类:

private static IMedicament CreateNew(IMedicament emptyType, string id)
{
    return new Medicament { Id = id };
}
private static IRefund CreateNew(IRefund emptyType, string id)
{
    return new Refund { Id = id };
}

RepositoryManager<Iabc> abcRepository = new RepositoryManager<Iabc>();
RepositoryManager<Ixyz> xyzRepository = new RepositoryManager<Ixyz>();

Iabc abc = abcRepository.GetOrCreate("12345");
Ixyz xyz = xyzRepository.GetOrCreate("12345");

所以使用T item = (T)CreateNew(new T(), id);不起作用,因为我必须告诉它 T 可以是 Iabc 或 Ixyz 类型,但是当我这样做时,我收到以下错误:

以下方法或属性之间的调用不明确:RepositoryManager<T>.CreateNew(IMedicament, string)RepositoryManager<T>.CreateNew(IRefund, string)

除了多次复制代码之外,如果我能做到这一点,那就太好了。

4

6 回答 6

2

为什么这不起作用?

public class RepositoryManager<T> : IRepositoryManager<T> where T : Ixyz, new()
{
    public T GetOrCreate(string id)
    {
        T item = (T)CreateNew(new T(), id);
        return item;
    }
}

另一种方法是,如果您不能使用 new() 是传入一个委托来创建对象(或兼容的类型):

public class RepositoryManager<T> : IRepositoryManager<T> where T : Ixyz
{
    private Func<T> _tConstructor;

    public RepositoryManager(Func<T> tConstructor)
    {
      this._tConstructor = tConstructor;
    }

    public T GetOrCreate(string id, )
    {
        T item = (T)CreateNew(this._tConstructor(), id);
        return item;
    }
}
于 2008-11-20T02:24:59.247 回答
2

我不确定我是否完全理解这个问题,但我以前使用过类似的东西。

public class Repository
{
    public T Create<T>(string id) where T : class
    {
        return Activator.CreateInstance(typeof(T), new[] { id }) as T;
    }
}
于 2008-11-20T03:04:34.643 回答
1

如果我明白你的问题是什么,基本上你想做(在某种意义上)RhinoMocks 所做的事情,除了 RhinoMocks 实际上从接口动态创建一个类,因为你想使用现有的类。

我对代码不够熟悉,不知道 RhinoMocks 是如何实现这一点的,但由于它是开源的,你可能会得到一些想法,但看看它的源代码。

http://ayende.com/projects/rhino-mocks/downloads.aspx

于 2008-11-20T01:58:06.960 回答
1

让 IRefund 和 IMedicament 实现一个都有 Id 属性的共享接口怎么样?

于 2009-05-29T19:45:13.407 回答
0

前几天我自己也遇到了这个问题。问题是你不知道构造函数有多少参数。假设不需要,以下代码将起作用。

public void Method<T>()
{
  Type type = typeof(T);

  T newObject = (T)type.GetConstructor(new System.Type[] { }).Invoke(new object[] { });
}

该示例使用反射。如果您需要参数,则可以将对象放入代码中创建的数组中。

于 2008-11-20T02:19:01.757 回答
0

也许以下内容对您有用?1)创建一个字典,其中 type 是您的接口(T 参数),object 是可以创建的对象的虚拟实例,2)让您的虚拟对象成为实现 T 的新对象的工厂。

您的 RepositoryManager 只需要使用支持的接口-对象对初始化字典,其中多个接口可以映射到同一个对象(如果需要)。

于 2010-08-25T15:27:59.847 回答