Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/274.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# C语言中的Delphi类#_C#_.net_Delphi_Oop_Factory - Fatal编程技术网

C# 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; 实施 程序初始化

我知道以前有人问过这个问题,但我还没有看到一个简短、明确的答案,所以我希望他们不会删除这个问题,现在我会得到一个明确的答案:

我目前在C#5.0;工作。净额4.5;VS 2012。虽然我在C#方面做了很多工作,但我基本上是一个德尔福人

在Delphi中,我编写了数百个类工厂,它们使用以下类型的设计(这里简化了很多):

单元工厂;
接口
类型
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);
    }