繁体   English   中英

C#-根据泛型类中提供的接口实例化一个类

[英]C# - Instantiate a class depending on a provided interface in a generic class

我有一个泛型函数,将接口作为类型,现在在一种情况下,我必须根据接口创建一个新类。 我一直在考虑它,解决该问题的方法是使用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;
    }
}

如果我不是通过接口来获取对象,则可以使用visitor模式来确定要实例化的类,但是根据提供的接口,我似乎无法弄清楚该类。

我的另一个想法是,是否可以像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)

如果我能做到这一点,除了将代码复制几次,那将是很好的。

为何不起作用?

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;
    }
}

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

public class Repository
{
    public T Create<T>(string id) where T : class
    {
        return Activator.CreateInstance(typeof(T), new[] { id }) as T;
    }
}

如果我了解您的问题是什么,那么基本上您想(在某种意义上)做RhinoMocks的工作,除了RhinoMocks实际上是从接口动态创建一个类,而您要在其中使用现有的类。

我对代码不太熟悉,无法知道RhinoMocks是如何做到这一点的,但是由于它是开源的,因此您可以了解一些想法,但可以查看其源代码。

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

如何使IRefund和IMedicament实现一个都具有ID属性的共享接口?

前几天,我自己遇到了这个问题。 该问题是您不知道构造函数采用多少个参数。 假设不采取任何措施,以下代码将起作用。

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

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

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM