2013-04-08 27 views
10

Bu sorunun daha önce sorulmuş olduğunu biliyorum, ancak henüz kısa ve net bir cevap görmedim, bu yüzden bu soruyu kaldırmayacaklarını umuyorum ve şimdi net bir cevap alacağım:Delphi Sınıfı C#

Şu anda C# 5.0; .NET 4.5; VS 2012. C# ile çok yapmam rağmen çoğunlukla bir Delphi adamım. Şimdi

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. 

:

Delphi ben tasarımın aşağıdaki tür (COK BURADA BASİTLEŞTİRİLMİŞ) kullanan sınıf fabrikaların yüzlerce yazdım NASIL C# böyle bir şey yapacağız ?! C# türünde NO 'sınıfı var gibi görünüyor. Bir şey mi eksik? Bu tip bir sınıf fabrikasını C# 'da basit ve zarif bir şekilde nasıl uygularım? Bu tasarım Python'da da uygulanabilir - neden C# daha kötü olmalı ?!

+0

Are TMyClass1 ve TMyClass2 alt sınıfları bir NullPointerException atacağım? – Martheen

+0

@martheen evet, bu TMyClass –

cevap

9

Sen Tip kullanabilirsiniz:

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(....); 
} 

Ama genel yöntemi kullanmak gerektiğini düşünüyorum:

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; 
} 

Ve: İşte

public T Factory<T>(): where T is MyBaseClass 
{ 
    var type = typeof(T); 
    var constructor = type.GetConstructor(....); 
    return constructor.Invoke(....) as T; 
} 

parametreli yapımı için bir çeşittir Tabii; bunun, eşleşen yapıcısı bulamazsa İlk örnekte olduğu gibi, bu ... TMyClass ait

+0

Teşekkürler - bunu da kontrol edecek. Burada başka bir cevap da Invoke() kullanıyor ve ben de web üzerinde kodları da fabrika yöntemlerinde kullandım. – Vector

+1

Bu, belirli bir kurucuya sahip bir alt sınıfı uygulayamayacağınız/kullanamayacağınız için, bunun Delphi'den biraz daha az güçlü olduğunu unutmayın. (Ayrıca, C# 'daki parametrelerin dışındaki yapıcılar için genel bir kısıtlama yoktur.) –

+2

@ O.R.Mapper: Delphi jenerik yapıcı kısıtlayıcı da parametresiz olanlar içindir. Bu, yalnızca sınıf sınıf hiyerarşisinde tanımlandığı şekilde, özgül sınıfları, meta sınıfının tanımlandığı sınıfa, TObject öğesinden de kullanabileceğiniz meta sınıfları kullanırken kullanılır. –

1

Eğer doğru anladıysan, statik bir sınıfa başvurmak istiyorsan, düzeltin. Bu C# mümkün değildir. fabrika yöntemi uygulamasının

sadece bir örnek: http://www.codeproject.com/Tips/328826/implementing-Factory-Method-in-Csharp

+0

sınıfına göre zorlanır Delphi'de 'Class of', bir metaSınıfıdır - bu, temel sınıfın tüm alt öğelerini genel olarak temsil edebilen ve temsil edilen alt sınıfa bağlı olarak polimorfizm ile çalışabilen bir tiptir. Statik sınıflarla ilgisi yok. – Vector

1

C# dili meta sınıfları desteklemez.

Fabrikanızı başka bir şekilde uygulamak zorundasınız. Tek yönlü bir enum üzerinde bir switch deyimi kullanmaktır:

switch (aEnum) 
{ 
    case myEnum1: 
     return new MyClass1(); 
    case myEnum2: 
     return new MyClass2(); 
    ..... 
} 

başka sık kullanılan seçenek yapmaya alışık ne daha yakın kod yazmak sağlayacak yansıması ile yapmaktır.

Ayrıca, bir başka seçenek de sınıfınızın sözlüğünü, nesnenizin yeni bir örneğini döndüren delegelerin sözlüğü ile değiştirmektir. Bu seçenek lambda sözdizimi ile çok temiz kod verir.

Yansımanın dezavantajı, derleme zamanı tipi güvenliğinden vazgeçmenizdir. Bu yüzden, yansıma tabanlı yaklaşım, söz konusu sorudaki Delphi koduna muhtemelen en yakın olsa da, kişisel olarak tercih edeceğim yol değil.

Delphi çözümünüzü bu yaklaşımı istemeyen bir dile sokmaya çalışmak yerine, en idiomatik C# çözümünü aramanızı öneririm. Sınıf fabrikası için bir web araması ile başlayın.

+0

+1 - Teşekkürler. Evet, {case:} anahtarını biliyorum - Delphi, sizin de bildiğiniz gibi, enumlar için de var. 'Sınıf fabrikası için bir web araması ile başla' - Tekrar teşekkürler. Şimdi tüm saygımla lütfen tekrar sorumu okuyun. :-) – Vector

+1

Sanırım sorumu anladım. Web üzerinde çeşitli C# fabrikaları örnekleri bulacağınızı kastediyorum. Onlara bir göz atın ve en sevdiğiniz yaklaşımı seçin. –

+0

+1 OP dedi ki: "umuyoruz ... Şimdi net bir cevap alacağım" - bu bir web araması anlamına gelmez. Bu yüzden OP bu soruyu sordu. :-) – Vector

4
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); 
    } 
+0

Bu harika görünüyor. Bunu kontrol etmemiz gerekiyor. Ama '=>' C# sözdizimi bilmiyorum, ya da yanlışlıkla C++ karıştırdınız mı? Sanırım C# 'da bir kurulacak bir dilde kurucu func'i sarmalısın. – Vector

+5

@Mikey: Bu bir [lambda ifadesi] (http://msdn.microsoft.com/en-us/library/bb397687.aspx). –

+0

@O. R. Mapper - Tamam teşekkürler. .NET'i 2.0, VS 2005'ten beri kullanmıyorum. :-) Benim sorumun nedenlerinden biri, o zamandan bu yana yardımcı olacak yeni bir şey olup olmadığını merak ediyordum. Görünüşe göre ... – Vector