使用通用类型或接口的C#集合
我有一组实现接口(IMyClass
)的类(MyClass1, MyClass2, MyClass3
)。使用通用类型或接口的C#集合
我感兴趣的创建方法来填充,并返回有共同的接口MyClass
X
(List<IMyClass>
)对象的列表(Collection.Generics.Lists<>
)。但是如何?
每个班级都有一个构造函数MyClass
X
它做了一些不同的事情。所以我不能创建一个BaseClass并为所有人使用通用构造函数。
通过界面我不能这样做:
public List<IMyClass> Fill(string[] ItemsPassedByParam, IMyClass InstanceOfMyClassX)
List MyList = new List<IMyClass>();
foreach (item in ItemsPassedByParam)
{
MyList.Add (new IMyClass (item)); //can't do new from an Interface!!
}
}
我也尝试过使用泛型类型,TMyClass在下面的例子,但也很适合我(虽然我不是泛型类型非常深刻的概念):
public List<TMyClass> Fill(string[] ItemsPassedByParam, Type TypeOfMyClassX)
List MyList = new List <TMyClass>();
foreach (item in ItemsPassedByParam)
{
MyList.Add (new TMyClass (item)); //can't do new from a Generic Type!!
}
}
我试图也来外部的MyClass
X
在方法的构造内的代码,但我不能调用该方法因为去对象未初始化(没有new()
)。
在这些情况下是哪种解决方案?
提前致谢!
这听起来像你想的填充方法来创建从字符串值传递的一个List<T>
,其中T
是推导IMyClass
。
您需要做的是将工厂函数传递给Fill方法,该方法允许创建IMyClass
派生实例。
public List<IMyClass> Fill(
string[] ItemsPassedByParam,
Func<string,IMyClass> createFunc)
List MyList = new List<IMyClass>();
foreach (item in ItemsPassedByParam) {
MyList.Add(createFunc(item));
}
}
然后,在你打电话填补你可以选择使用
string[] items = ...;
List<IMyClass> list1 = Fill(items, item => new MyClass1(item));
List<IMyClass> list2 = Fill(items, item => new MyClass2(item));
谢谢Jared! 我做了你和贾斯汀Niessner的解决方案之间的混合。因为关于女巫的开发时间提醒是使用构造函数对我来说不是很实用。所以我做了一个'MyClassFactory.CreateInstance()'也是一个'MyClassFactory.GetConstrucor(类型)'来获得拨款的构造。 – Alex 2010-08-20 11:37:08
这里最好的选择是创建一个处理取参数IMyClassFactory,搞清楚构建哪个具体类型,调用构造函数,并返回它:
public class IMyClassFactory
{
public static IMyClass CreateInstance(string item)
{
switch(item)
{
case "SomeValue":
case "SomeValue2":
return new MyClass1(item);
case "SomeOtherValue":
return new MyClass2(item);
}
}
}
那家工厂显然假定您可以推断键入从传入工厂的字符串。很有可能情况并非如此,在这种情况下,您需要添加另一个参数,以便您推断要实例化的具体类型。
一旦你的工厂,那么你可以让你的原来的方法使用该工厂:
public List<IMyClass> Fill(string[] ItemsPassedByParam)
{
List MyList = new List<IMyClass>();
foreach (item in ItemsPassedByParam)
{
MyList.Add(IMyClassFactory.CreateInstance(item));
}
}
IMyClassFactory?用“我”?该命名约定会导致混淆... – 2010-08-19 15:31:01
谢谢贾斯汀! 按照你的方法我建你'MyClassFactory.CreateInstance()',也做了'MyClassFactory.GetConstrucor(T型)'用贾里德 解决方案。 – Alex 2010-08-20 11:40:03
也许你可以只使用工厂模式在这里,这取决于你如何判断需要哪种类型的其中IMyClass
推导的地方。
也许您需要使用反射并调用ConstructorInfo(将参数传递给构造函数,返回一个对象,适合在模板方法中构建,但也适用于在运行时炸毁在编译时会被捕获的东西)。
后者似乎离你最近一直在尝试什么,但如果你可以从一个更类型安全的工厂做的事情,然后这可能是要走的路。
public static T BuildOne(SomeParamType myParam)
{
ConstructorInfo constrInfo = typeof(T).GetConstructor(BindingFlags.Public | BindingFlags.Instance, null, new Type[]{typeof(SomeParamType)}, null);
return (T)constrInfo.Invoke(new object[]{myParam});
}
您不能创建一个接口的实例,但你可以创建一个通用型的实例 - 只要它有一个默认的构造函数。您可以将该项目传递给实例,而不是使用构造函数注入。
public List<TMyClass> Fill(string[] ItemsPassedByParam)
where TMyClass : IMyClass, new() {
...
IMyClass inst = new TMyClass();
inst.SetItem(item);
myList.Add(inst);
...
}
调用new TMyClass
与调用Activator.CreateInstance<TMyClass>()
通用的CreateInstance不允许参数传递给构造相同的效果,但你可以用非genric的CreateInstance通过他们。
public List<TMyClass> Fill(string[] ItemsPassedByParam) {
...
myList.Add((IMyList)Activator.CreateInstance(typeof(TMyClass), item));
...
}
什么是'item'?它是否确定类型? – cjk 2010-08-19 15:26:42
此外,什么是 “新目录();”应该是?没有什么可以想象的编译。 –
2010-08-19 15:28:25