我有一组实现接口(MyClass1, MyClass2, MyClass3
)的类(IMyClass
)。
我有兴趣创建一个方法来填充和返回具有公共接口Collection.Generics.Lists<>
MyClass
({{1}的对象的列表(X
) }})。但是如何?
每个类都有一个构造函数List<IMyClass>
MyClass
,它可以做一些与众不同的事情。所以我无法创建 BaseClass 并为所有人使用通用构造函数。
通过界面我无法做到:
X
此外,我尝试在下一个示例中使用泛型类型TMyClass,但两者都没有对我有用(尽管我对泛型类型的概念不是很深):
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!!
}
}
我还尝试在方法中将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
的构造函数中的代码外部化,但我无法调用该方法,因为de object未初始化(没有X
)。
在这些情况下,这是解决方案吗?
提前致谢!
答案 0 :(得分:7)
听起来您希望Fill方法根据传入的字符串值创建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));
}
}
然后在您调用Fill的地方,您可以选择使用<{1}}的派生
IMyClass
答案 1 :(得分:2)
这里最好的选择是创建一个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));
}
}
答案 2 :(得分:2)
您无法创建接口的实例,但您可以创建泛型类型的实例 - 前提是它具有默认构造函数。然后,您可以将项目传递给属性或方法,而不是使用构造函数注入。
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));
...
}
答案 3 :(得分:1)
也许你可以在这里使用工厂模式,具体取决于你如何判断需要哪种类型。
也许你需要使用反射并调用一个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});
}