2010-01-11 30 views
8

Bunun mümkün olup olmadığını bilmiyorum, ancak bazı birim testlerimde, farklı nesneleri aynı argümanlarla başlatabilirim. Bazı değişkende bu argümanları saklamak mümkün olmak ister ve sadece yapmanın böylece yerine o değişkenle çok parametreli nesne yapıcı başlatmak olacaktır:C# Birden çok bağımsız değişken bir parametreden geçirme parametresi geçiren

MagicalArgumentsContainer args = (arg1, arg2, arg3, arg4); 
Thing thing1 = new Thing(args); 
Thing thing2 = new Thing(args); 
Thing thing3 = new Thing(args); 

: Aşağıdaki yapabileceğini

Thing thing1 = new Thing(arg1, arg2, arg3, arg4); 
Thing thing2 = new Thing(arg1, arg2, arg3, arg4); 
Thing thing3 = new Thing(arg1, arg2, arg3, arg4); 

Thing 'un yapıcısını geçersiz kılmadan, el ile dışarı çıkarıp argümanları dışarıdan aktaran bir liste almak için herhangi bir yolu var mı? Belki biraz C# syntactic şeker? Yani

+1

Hayır, = Ruby kullanmak istiyorum). –

+2

Python'un argümanı açma paketi bir nimettir! –

+1

Ben _did_ kendime, bu projeyi Ruby kullanıyorum, bu soruyu sormak zorunda kalmayacağımı düşünüyorum. –

cevap

13

, bu var:

Func<Thing> f =() => new Thing(arg1, arg2, arg3, arg4); 
Thing thing1 = f(); 
Thing thing2 = f(); 
Thing thing3 = f(); 
Thing thing4 = f(); 

Sadece closure semantics dikkatli olun.

+1

evet, InLine minik ObjectFactory gibi, ancak arg1-arg4'ün referans türleri olması durumunda, tüm nesnelerin bu nesneleri paylaşacaklarını, eğer değer tipiyse veya paylaşıldıklarında hiç umursamıyorsanız, o zaman muhtemelen en kolay –

+0

Benim durumumda, arg1-4 dizeleri, bu yüzden hepsi iyi. –

1

bu, sizin Thing1 varsayarak önemsiz bir nesnedir de var ve sadece sığ bir kopyasına gerek: Bu birçok yapmanız gerekiyorsa

Thing thing1 = new Thing(arg1, arg2, arg3, arg4); 
Thing thing2 = (Thing)thing1.MemberwiseClone(); 
0

Ayrıca döngü için nesnelerin dizisi ve kullanabilirsiniz zamanlar.

1

GimmieAThing, biraz jenerik kullanarak GimmieAThing<T> gibi bir şeye yeniden yazabilir misiniz?

public class MagicalArgumentsContainer 
    { 
      object[] _myParams; 

      public MagicalArgumentsContainer (params object[] myParams) 
      { 
      _myParams = myParams; 
      } 

      public Thing GimmieAThing() 
      { 
    return new Thing(_myParams[0], _myParams[1], _myParams[2], _myParams[3]); 
     } 
    } 
3

Eh ben nasıl tipi T yeni bir örneğini yapmak için IoC söyleyebilen ve sadece size vermek IoC sormak yani, aynı zamanda bir ObjectFactory teklif bu birkaç beri, bir IoC kapsayıcı kullanmak sanırım bunun bir örneği. Bir IoC almak istemiyorsanız

Ancak kendine

public MagicFactory 
{ 
    T arg1, T2 arg2, T3 arg3,.., TN argN; 

    public MagicFactory(T1 a1,..., TN aN) 
    { 
     this.arg1=a1; 
     ... 
     this.argN = an; 
    } 

    public Thing GimmeDaThing() 
    { 
     return new Thing(this.arg1,...,this.argN); 
    } 
} 

ancak akılda tutulması biraz fabrika sınıfını yapabilir argümanlar değer türünde değilse, o Thing ait tüm örneklerini olacak o Aynı cisimlere atıfta bulunursunuz, bu yüzden, nesnelerin farklı bir örneğine sahip olsanız da, hepsi aynı arg1'e işaret ederler. Bunu aslında parametresinde bir Func içinde almaktır düzeltmek için yapabileceği, bu yüzden aslında bir yenisi oluşturabilir Ne:

public MagicFactory 
{ 
    Func<T1> arg1, ,.., Func<TN> argN; 

    public MagicFactory(Func<T1> a1,..., Func<TN> aN) 
    { 
     this.arg1=a1; 
     ... 
     this.argN = an; 
    } 

    public Thing GimmeDaThing() 
    { 
     return new Thing(this.arg1(),...,this.argN()); 
    } 
} 

ve bunu şöyle çağırır:

var magicContainer = new MagicFactory(()=> new T1(...),...,()=>new T2(..); 


var thing1 = magicContainer.GimmeDaThing(); 
var thing1 = magicContainer.GimmeDaThing(); 
var thing1 = magicContainer.GimmeDaThing(); 
var thing1 = magicContainer.GimmeDaThing(); 

ve Her seferinde her biri kendi eşya nesnelerine sahip yeni bir Thing örneği alırsınız.

+1

public MagicFactory ? – gingerbreadboy

1

Test Data Builder modelini incelemeyi öneririm. Bağımsız olarak değişiklik yapmak, yeniden kullanmak ve benzeri birçok parametreniz olduğunda gerçekten iyi çalışır.

properties + object initializers for 'flat' classes veya alternatif olarak akışkan yöntem zincirlemeyi kullanabilirsiniz. Her ikisiyle de oynadım ve her birinin avantajları var.

Faydaları:

  • Sen değişkenleri yakalayabilir/Tek gereken değerleri basit türleri ise bir nesne oluşturmak için kullanıldığını
  • Bir oluşturucu örneğini yeniden kullanabilir değerleri ve/bağımsız bir şekilde, gürültü /kod kopyalama olmadan veya iletmenin (değer türleri, şeritler gibi)
  • her parametre cTOR değişebilir Bu testler yapar gibi gerçekten güzel okuyor, yerine hangi cetvel param olduğunu hatırlamak zorunda, ismini görüyorsunuz.

Her bir parametrenin yeni örneklerini oluşturmanız gerekiyorsa, vurucunun yanıtını gözden geçirin.

public class ThingBuilder 
{ 
    // set up defaults so that we don't need to set them unless required 
    private string m_bongoName = "some name"; 
    private DateTime m_dateTime = new DateTime(2001, 1, 1); 
    private int m_anotherArg = 5; 
    private bool m_isThisIsGettingTedious = true; 

    public ThingBuilder BongoName(string bongoName) 
    { 
     m_bongoName = bongoName; 
     return this; 
    } 

    public ThingBuilder DateTime(DateTime dateTime) 
    { 
     m_dateTime = dateTime; 
     return this;  
    } 

    // etc. for properties 3...N 

    public Thing Build() 
    {  
     return new Thing(m_bongoName, m_dateTime, m_anotherArg, m_isThisGettingTedious); 
    } 
} 

Kullanımı (örneğin bir kez):

// notice that the parameters are now explicitly named + readable! 
Thingy builtInstance = new ThingBuilder() 
          .BongoName("um bongo") 
          .DateTime(DateTime.Now) 
          .GettingTedious(true) 
          .Build(); 

Çok Örnekler:

var builder = new ThingBuilder() 
        .BongoName("um bongo") 
        .DateTime(DateTime.Now) 
        .GettingTedious(true); 

// let's make multiple objects 
Thing builtThing = builder.Build(); 
Thing anotherBuiltThing = builder.Build(); 
1

kullanın böylece gibi yöntemde params beyan

Neyse

, burada bazı kod:

public Thing(params string[] args) 
{ 
    foreach(string s in args) 
    { 
     ... 
    } 
} 

ve aşağıdakileri yapmanızı sağlayacaktır:

result = Things(arg1) 
result = Things(arg1,arg2) 
result = Things(arg1,arg2,arg3) 
result = Things(arg1,arg2,arg3,arg4) 
İlgili konular