2011-10-23 173 views
0

我現在做:鑄造泛型類型的非泛型方法

void Main() 
{ 
    var command1 = new PersistenceCommand(new MyIntBO()); 
    var command2 = new PersistenceCommand(new MyGuidBO()); 
    var command3 = new PersistenceCommand(new PersistentBO()); 

    Console.WriteLine(command1.ToString()); 
    Console.WriteLine(command2.ToString()); 
    Console.WriteLine(command3.ToString()); 
} 

public class PersistenceCommand 
{ 
    public PersistenceCommand(PersistentBO businessObject) 
    { 
     _businessObject = businessObject; 
    } 

    public override string ToString() 
    { 
     string result = _businessObject.GetType().Name; 

     var keyed = _businessObject as IPrimaryKeyed<int>; 

     if (keyed != null) 
     { 
      result += " " + keyed.Id.ToString(); 
     } 

     return result; 
    } 

    private readonly PersistentBO _businessObject; 
} 

public interface IPrimaryKeyed<out TKey> 
{ 
    TKey Id { get; } 
} 

public class PersistentBO {} 

public class MyIntBO : PersistentBO, IPrimaryKeyed<int> 
{ 
    public int Id { get { return 1008; } } 
} 

public class MyGuidBO : PersistentBO, IPrimaryKeyed<Guid> 
{ 
    public Guid Id 
    { 
     get 
     { 
      return new Guid("6135d49b-81bb-43d4-9b74-dd84c2d3cc29"); 
     } 
    } 
} 

此打印:

MyIntBO 1008 
MyGuidBO 
PersistentBO

我想它想打印:

MyIntBO 1008 
MyGuidBO 6135d49b-81bb-43d4-9b74-dd84c2d3cc29 
PersistentBO

什麼是最優雅的方式來做到這一點?

我想支持所有類型的鍵 - int,long,Guid等 - 所以我寧願不做多個演員。請注意,並非每個業務對象都實現該接口(有些沒有單個主鍵)。

我意識到我可以使用反射並嘗試訪問Id屬性。我想知道是否有更好的解決方案。

澄清:爲了解決@Acaz索薩和@Petar伊萬諾夫的答案,我們有幾十個散落在已經實現IPrimaryKeyed<T>多個組件類。我不想通過擴展接口合約來打破所有這些問題。如果我從頭開始設計,他們的解決方案就可以工作。

回答

1

使用反射似乎不是一個壞的方法去這裏。

ToString方法:

// for getting the Id prop 
var identProp = _businessObject.GetType().GetProperty("Id"); 
string result = _businessObject.GetType().Name; 

if (identProp != null) 
{ 
    result += " " + identProp.GetValue(_businessObject, null).ToString(); 
} 
+0

+1 - 如果我走這條路線,可以節省一些時間。請注意'stuff'應該是'_businessObject'。我也可以緩存'GetType()'的結果。 – TrueWill

+0

對錯字很好,固定 –

+0

這就是我最終使用的。我爲CanRead添加了一個檢查,並且GetValue的結果不爲null。 – TrueWill

1

的問題是在該行:

var keyed = _businessObject as IPrimaryKeyed<int>; 

你的另一種類型是不IPrimaryKeyed<int>IPrimaryKeyed<Guid>,那麼if (keyed != null)是假的。

你可以試着這樣做:

static void Main() 
{ 
    var command1 = new PersistenceCommand(new MyIntBO()); 
    var command2 = new PersistenceCommand(new MyGuidBO()); 
    var command3 = new PersistenceCommand(new PersistentBO()); 

    Console.WriteLine(command1.ToString()); 
    Console.WriteLine(command2.ToString()); 
    Console.WriteLine(command3.ToString()); 
    Console.ReadLine(); 
} 

public class PersistenceCommand 
{ 
    public PersistenceCommand(PersistentBO businessObject) 
    { 
     _businessObject = businessObject; 
    } 

    public override string ToString() 
    { 
     string result = _businessObject.GetType().Name; 

     var keyed = _businessObject as IPrimaryKeyed; 

     if (keyed != null) 
     { 
      result += " " + keyed.Id.ToString(); 
     } 

     return result; 
    } 

    private readonly PersistentBO _businessObject; 
} 

public interface IPrimaryKeyed 
{ 
    object Id { get; } 
} 

public class PersistentBO { } 

public class MyIntBO : PersistentBO, IPrimaryKeyed 
{ 
    public object Id { get { return 1008; } } 
} 

public class MyGuidBO : PersistentBO, IPrimaryKeyed 
{ 
    public object Id { get { return new Guid("6135d49b-81bb-43d4-9b74-dd84c2d3cc29"); } } 
} 
+0

是的,我知道問題所在。請看我對答案的澄清。還要注意現有的接口在其他地方使用;我不想簡單地刪除泛型。如果不是因爲我的限制,@Petar Ivanov的類似解決方案可行。 +1,但。 – TrueWill

2

只要創建一個非通用接口和更換一般一個與通用抽象類。然後檢查接口:

public interface IPrimaryKeyed 
    { 
     object ObjId { get; } 
    } 

    public abstract class PrimaryKeyed<TKey> : IPrimaryKeyed 
    { 
     public object ObjId { get { return Id; } } 
     public abstract TKey Id { get; } 
    } 

--- 

public override string ToString() 
{ 
    string result = _businessObject.GetType().Name; 

    var keyed = _businessObject as IPrimaryKeyed; 

    if (keyed != null) 
    { 
     result += " " + keyed.ObjId.ToString(); 
    } 

    return result; 
} 
+0

+1爲一個非常優雅的解決方案,如果我們從一開始就設計它,這將是可行的。請看我上面的澄清爲什麼這不是我的情況最佳。我的道歉不包括我原來的帖子。 – TrueWill

+0

順便說一句,我不能使用抽象類,因爲我已經有了一個必需的基類,C#是單繼承。我必須使用'public interface IPrimaryKeyed :IPrimaryKeyed'並在每個業務對象上實現該屬性。他們生成的代碼,所以它是可行的,但它會是一個痛苦。 – TrueWill