2015-09-10 20 views
2

作爲測試庫的一部分,我想定義一個接口,它說'這個對象知道如何隨機初始化自己'。如果隨機填充對象的成員是引用,則隨機初始化應該能夠爲這些成員分配null可能聲明包含擴展的接口嗎?

如果我這樣做了一個類,代碼可能看起來像這樣

public class QWorker 
{ 
    double mxVal = 0; 

    public void fillRandomly(System.Random xRng) 
    { 
     mxVal = xRng.NextDouble(); 
    } 
} 

public class QBoss 
{ 
    public QWorker mxWorker; 

    void fillRandomly(System.Random xRng) 
    { 
     if (xRng.Next() % 2 == 1) 
      x1 = null; 
     else 
     { 
      x1 = new QWorker(); 
      x1.fillRandomly(xRng); 
     } 
    }  
} 

現在,如果QBoss了多張引用類型的成員,如果/否則會對每一個成員來完成。它看起來很醜,維護起來可能很麻煩。爲了cimrcumvent,我想出了下面的示例代碼:

public interface QIRandomizable<T> where T : new() 
{ 
    static void fillRandomly(this System.Random xThis, ref T xRef); // XXX 
} 

class QWorker : QIRandomizable<QWorker> 
{ 
    public double mxDouble; 
} 

public static class QWorkerExtensions 
{ 
    public static void fillRandomly(this System.Random xThis, ref QWorker xRef) 
    { 
     if ((xThis.Next() % 2) == 1) 
      xRef = null; 
     else 
     { 
      xRef = new QWorker(); 
      xRef.mxDouble = xThis.NextDouble(); 
     } 
    } 
} 

public class QBoss : QIRandomizable<QBoss> 
{ 
    public QWorker mx1; 
    public QWorker mx2; 

    public static void fillRandomly(this System.Random xThis, ref QBoss xRef) 
    { 
     xRef = new QBoss(); 
     xThis.fillRandomly(ref xRef.mxMember1); // can be null 
     xThis.fillRandomly(ref xRef.mxMember2); // can be null 
    } 
} 

然而,這並不編譯,第一個問題是行標XXX - static關鍵字不屬於那裏。

結果,我想問下:

  1. 是否有可能宣佈的接口與內部的擴展?
  2. 如果是,我應該改變什麼?
  3. 如果沒有,是否有不同的方式來完成我想要的?

任何幫助是非常讚賞, 丹尼爾

+0

這是你在找什麼:http://stackoverflow.com/questions/1825952/how-to-create-a-generic-擴展方法 – PaulF

+0

@PaulF:對不起,我不能看到相似之處。 –

回答

0
  1. 不,你不能。這是因爲您只能在接口上聲明實例方法,並且擴展方法必須是靜態的。

你可以嘗試這樣的事情:

public interface IDoesSomething 
{ 
    void fillRandomly(Random r); 
} 
public class QBoss 
{ 
    public double mx1 { get; set; } 
    public double mx2 { get; set; } 
    public int mx3 { get; set; } 

    public object refType { get; set; } 

    public void fillRandomly(Random r) 
    { 
     FillRandom(GetProps(this), this, r);  
    } 
} 


public static IEnumerable<PropertyInfo> GetProps(object blah) 
{ 
    return blah.GetType().GetProperties(); 
} 

public static void FillRandom(IEnumerable<PropertyInfo> obj, object onObj, Random r) 
{ 
    Action<PropertyInfo, object> setVal = (prop, val) => { prop.SetValue(onObj, val); }; 
    foreach (var o in obj) 
    { 
     if (!o.PropertyType.IsValueType) 
     { 
      if (r.Next() % 2 != 1) 
      { 
       var v = Activator.CreateInstance(o.PropertyType); 
       setVal(o, v); 
       var id = v as IDoesSomething; 
       if (id != null) 
        id.fillRandomly(r); 
      } 
     } 
     if (o.PropertyType == typeof(double)) 
      setVal(o, r.NextDouble()); 
     if (o.PropertyType == typeof(int)) 
      setVal(o, (int)(r.NextDouble() * 100)); 

     //etc, etc 
    } 
} 

在這裏,你決定做什麼一次,並設置屬性。這目前僅適用於性能,而不是字段,所以您可能要重構它有點採取兩種FieldInfoPropertyInfo

測試它產生:

MX1 0.786868741170908
MX2 0.434705327001729
MX3 51
refType對象

+0

非常感謝。這超出了我目前的C#知識水平,並且我有截止日期。不過,我會喜歡這個以後學習新東西。 –