[英]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是如何做到这一点的,但是由于它是开源的,因此您可以了解一些想法,但可以查看其源代码。
如何使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.