Delphi Class of in C#
本文关键字:in of Class Delphi | 更新日期: 2023-09-27 18:08:04
我知道这个问题以前已经问过了,但是我还没有看到一个简短,明确的答案,所以我希望他们不会删除这个问题,我现在将得到一个明确的答案:
我目前正在使用c# 5.0;net 4.5;VS 2012。我主要是Delphi的家伙,虽然我做了很多与c#。
在Delphi中,我已经编写了数百个类工厂,它们使用以下类型的设计(这里简化了很多):
unit uFactory;
interface
type
TClassofMyClass = class of TMyClass;
TFactoryDict = TDictionary<TMyEnum, TClassofMyClass>;
var fDict:TFactoryDict;
implementation
procedure initDict;
begin
fDict:=TFactoryDict.create;
fDict.add(myEnum1, TMyClass1);
fDict.add(myEnum2, TMyClass2);
fDict.add(myEnum3, TMyClass3);
end;
function Factory(const aEnum: TMyEnum): TMyClass;
var
ClassofMyClass: TClassofMyClass;
begin
if fDict.TryGetValue(aEnum, ClassofMyClass) then
result := ClassofMyClass.Create(aParam);
end;
end.
现在:我如何在c#中做这样的事情?!似乎在c#中没有 '类'类型。我错过什么了吗?如何在c#中简单而优雅地实现这种类型的类工厂?这种设计也可以在Python中实现——为什么c#会更糟呢?
您可以使用Type:
Dictionary<ClassEnum, Type> TypeDictionary = new Dictionary<ClassEnum, Type>();
public void InitDictionary()
{
TypeDictionary.Add(ClassEnum.FirstClass, typeof(FirstClass));
//etc...
}
public object Factory(ClassEnum type)
{
if (!TypeDictionary.ContainsKey(type))
return null;
var constructor = TypeDictionary[type].GetConstructor(....);
return constructor.Invoke(....);
}
但是我认为你应该使用泛型方法:
public T Factory<T>(): where T is MyBaseClass
{
var type = typeof(T);
var constructor = type.GetConstructor(....);
return constructor.Invoke(....) as T;
}
下面是参数化构造的一个变种:
public T Factory<T>(params object[] args): where T is MyBaseClass
{
var argList = new List<object>(args);
var type = typeof(T);
var argtypes = argList.Select(o => o.GetType()).ToArray();
var constructor = type.GetConstructor(argtypes);
return constructor.Invoke(args) as T;
}
当然;与第一个示例一样,如果找不到匹配的构造函数,它将抛出nullpointerexception…
class Potato
{
}
class Potato1 : Potato
{
public Potato1(object[] param) { }
}
class Potato2 : Potato
{
public Potato2(object[] param);
}
enum MyEnum
{
E1, E2
}
Dictionary<MyEnum, Func<object[], Potato>> dict = new Dictionary<MyEnum, Func<object[], Potato>>(){
{MyEnum.E1,(d)=>new Potato1(d)},
{MyEnum.E2,(d)=>new Potato2(d)}
};
Potato Factory(MyEnum e, object[] param)
{
return dict[e](param);
}
如果我理解你正确,你想有一个静态类的引用。这在c#中是不可能的
只是一个工厂方法实现的例子:http://www.codeproject.com/Tips/328826/implementing-Factory-Method-in-Csharp
c#语言不支持元类。
所以你必须用另一种方式实现你的工厂。一种方法是在enum上使用switch语句:
switch (aEnum)
{
case myEnum1:
return new MyClass1();
case myEnum2:
return new MyClass2();
.....
}
另一个常用的选项是使用反射,这将允许您编写更接近您习惯做的代码。
还有一个选择是用一个委托字典替换你的类字典,委托字典返回你的对象的一个新实例。使用lambda语法,该选项产生非常干净的代码。
反射的缺点是放弃编译时类型安全。因此,虽然基于反射的方法可能最接近问题中的Delphi代码,但这不是我个人选择的路线。
与其试图将Delphi解决方案硬塞进一种不需要这种方法的语言中,我建议您寻找最惯用的c#解决方案。从web搜索类工厂开始。