C# C语言中的Delphi类#
我知道以前有人问过这个问题,但我还没有看到一个简短、明确的答案,所以我希望他们不会删除这个问题,现在我会得到一个明确的答案: 我目前在C#5.0;工作。净额4.5;VS 2012。虽然我在C#方面做了很多工作,但我基本上是一个德尔福人 在Delphi中,我编写了数百个类工厂,它们使用以下类型的设计(这里简化了很多):C# C语言中的Delphi类#,c#,.net,delphi,oop,factory,C#,.net,Delphi,Oop,Factory,我知道以前有人问过这个问题,但我还没有看到一个简短、明确的答案,所以我希望他们不会删除这个问题,现在我会得到一个明确的答案: 我目前在C#5.0;工作。净额4.5;VS 2012。虽然我在C#方面做了很多工作,但我基本上是一个德尔福人 在Delphi中,我编写了数百个类工厂,它们使用以下类型的设计(这里简化了很多): 单元工厂; 接口 类型 TClassofMyClass=TMyClass的类; TFactoryDict=t词典; var-fDict:TFactoryDict; 实施 程序初始化
单元工厂;
接口
类型
TClassofMyClass=TMyClass的类;
TFactoryDict=t词典;
var-fDict:TFactoryDict;
实施
程序初始化;
开始
fDict:=TFactoryDict.create;
fDict.add(myEnum1,TMyClass1);
fDict.add(myEnum2,TMyClass2);
fDict.add(myEnum3,TMyClass3);
结束;
函数工厂(const aEnum:TMyEnum):TMyClass;
变量
周期类:TCLASSOF周期类;
开始
如果fDict.TryGetValue(aEnum,ClassofMyClass)则
结果:=ClassofMyClass.Create(aParam);
结束;
结束。
现在:我如何在C#中做类似的事情?!似乎C#中没有类型的“class of”。我错过什么了吗?如何在C#中简单而优雅地实现这种类型的类工厂?这种设计也可以用Python实现——为什么C更糟糕 如果我理解您的意思,那么您希望有一个对静态类的引用。这在c#中是不可能的 工厂方法实现的一个示例: C语言不支持元类 所以你必须用另一种方式来实现你的工厂。一种方法是在枚举上使用switch语句:
switch (aEnum)
{
case myEnum1:
return new MyClass1();
case myEnum2:
return new MyClass2();
.....
}
另一个常用的选项是使用反射,这将允许您编写更接近您习惯的代码
还有一种选择是用委托字典替换类字典,委托字典返回对象的新实例。使用lambda语法,该选项生成非常干净的代码
反射的缺点是您放弃了编译时类型安全性。因此,虽然基于反射的方法可能最接近问题中的Delphi代码,但我个人不会选择这种方法
我建议您寻找最惯用的C#解决方案,而不是将您的Delphi解决方案硬塞进一种不需要这种方法的语言中。从类工厂的web搜索开始。您可以使用类型:
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(....);
}
Dictionary-TypeDictionary=newdictionary();
公共字典()
{
添加(ClassEnum.FirstClass,typeof(FirstClass));
//等等。。。
}
公共对象工厂(类枚举类型)
{
if(!TypeDictionary.ContainsKey(type))
返回null;
var constructor=TypeDictionary[type].GetConstructor(..);
返回构造函数.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是MyBaseClass
{
var类型=类型(T);
var constructor=type.GetConstructor(..);
将constructor.Invoke(..)作为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;
}
public T工厂(params对象[]args):其中T是MyBaseClass
{
var argList=新列表(args);
var类型=类型(T);
var argtypes=argList.Select(o=>o.GetType()).ToArray();
var constructor=type.GetConstructor(argtypes);
将constructor.Invoke(args)作为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);
}
{
}
第1类:马铃薯
{
公共Potato1(对象[]参数){}
}
第二类:马铃薯
{
公共Potato2(对象[]参数);
}
髓鞘
{
E1,E2
}
Dictionary dict=新字典(){
{MyEnum.E1,(d)=>新的Potato1(d)},
{MyEnum.E2,(d)=>新Potato2(d)}
};
马铃薯工厂(MyEnum e,对象[]参数)
{
返回dict[e](参数);
}
TMyClass的TMyClass1和TMyClass2子类是吗?@martheen是的,这是由TMyClass类强制执行的,这在C#?+1中仍然缺失-谢谢。是的,我知道开关{case:}-正如您所知,Delphi也有用于枚举的开关从网络搜索类工厂开始,再次感谢。现在,恕我直言,请再次阅读我的问题。:-)我想我理解这个问题。我的意思是你会在网上找到各种各样的C工厂的例子。看看它们,选择你最喜欢的方法。你得到了明确的答案。一个简单的语句,表示没有等价的类。我概述了实现工厂的三种可能的方法。我认为一些网络搜索会产生更多的想法。你可能已经做过了,只是想知道你是否可以用元类来做。嗯,不完全是。最接近元类的是使用反射。但是什么呢?我只是说,有很多方法可以办厂。很难推荐一个。你需要做出自己的选择。使用网络搜索会给你一些超出这里的额外想法。有什么害处?虽然我个人想不出任何超出我概述的想法,但我敢打赌一定有一些!这就是我不同意的地方。最接近您的代码的是基于反射的方法。但我会选择一本代表字典。我认为您需要针对该语言编程,而不是尝试将一种语言的解决方案应用于不适合的语言。我个人不喜欢反思的方法。除非别无选择,否则我会避免反思。这就是我最后一段的重点。@Mikey:这是一个。没有MyEnum数组不是很遗憾吗。。。在C#中,是需要调用的,还是可以编写存在于Oxygene中的dict[e]()@Martheen。我相信元类也是。“我不认为.net有太多限制。”米奇编辑了我的答案。如果您需要,可以将对象[]更改为更具体的示例。Hanks-也会检查这个。这里的另一个答案也使用Invoke(),我在
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);
}