2010-11-02 55 views
0

我有第三方設計糟糕的圖書館,我必須使用。
它擁有各種類型它與中,我們會打電話給他們SomeType1SomeType2
沒有這些類型都有一個共同的基類,但都具有不同的返回類型一個名爲Value屬性。
我想要做的就是能夠Mixin這個類,所以我可以打電話someType1Instance.ValuesomeType2Instance.Value,而不必關心它的結構類型和不關心返回類型是什麼(我可以使用object)。
所以我的代碼目前是:沒有基類問題,在這種特殊情況下如何使用Castle.DynamicProxy Mixin?

public interface ISomeType<V> 
{ 
    V Value {get; set;} 
} 

public interface ISomeTypeWrapper 
{ 
    object Value { get; set; } 
} 

public class SomeTypeWrapper<T> : ISomeTypeWrapper 
    where T : ISomeType<???> 
{ 
    T someType; 

    public SomeTypeWrapper(T wrappedSomeType) 
    { 
    someType = wrappedSomeType 
    } 

    public object Value 
    { 
    get { return someType.Value; } 
    set { someType.Value = value != null ? value : default(T); } 
    } 
} 

public class SomeType1 
{ 
    public int Value { get; set; } 
} 

public class SomeType2 
{ 
    public string Value { get; set; } 
} 

的問題是,我不知道是什麼牛逼可能直到運行時由於這樣的事實,我得到的對象的字典。

我可以迭代字典並使用反射來創建一個運行時的SomeWrapperType,但我想避免它。

如何將SomeType的concreate類型混入ISomeType?
我怎麼知道V型參數是什麼? (希望我有像C++一樣的typedefs和decltype)

我怎樣才能以最少的反射使用Mixin這些具有接口/基類的類?

+0

有多少類型,我們在談論什麼?什麼是第三方api? – Bronumski 2010-11-02 15:54:11

+0

13-14,microsoft dynamics crm。 – 2010-11-02 15:56:49

回答

1

您可以嘗試溫莎的Duck Typing Extensions。這意味着您需要註冊每個類型。

container 
    .Register(Component.For(typeof(SomeType1)).Duck<ISomeType>()) 
    .Register(Component.For(typeof(SomeType2)).Duck<ISomeType>()); 

如果名稱相似,您可以使用linq和寄存器AllTypes語法來減少代碼。

或者在短期內創建一個工廠,它可以返回您需要的對象,爲每個類型實現一個具體對象。不,你正在使用的界面,您可以在日後取出工廠,並與影響最小別的東西替代它:

public class SomeTypeWrapperFactory 
{ 
    public ISomeType<int> CreateWrapper(SomeType1 someType1) 
    { 
     return new SomeType1Wrapper(someType1); 
    } 

    public ISomeType<string> CreateWrapper(SomeType2 someType2) 
    { 
     return new SomeType2Wrapper(someType2); 
    } 
} 

public class SomeType1Wrapper : ISomeType<int> { ... } 
public class SomeType2Wrapper : ISomeType<int> { ... } 

不管你如何實現包裝的,可以單獨或使用神象類,你有能力改變包裝的完成方式並保持代碼的其餘部分清潔。

+0

「顯然,DeftTech生成的代理不能由DynamicProxy代理......所以不要試圖爲這些組件定義任何攔截器!再一次,最佳解決方案是使用DynamicProxy實現適當的鴨子輸入」。這是一個問題,我計劃攔截方法調用。 – 2010-11-02 16:32:08

+0

嘗試了工廠方法,因爲我不知道我的對象的類型是什麼,直到運行時纔得到我的字典。 – 2010-11-02 18:06:19

+0

這是我得到的最接近的。我將此標記爲接受的答案。 – 2010-11-16 10:51:36

1

爲什麼SomeTypeWrapper而不是SomeObjectWrapper?

public class SomeObjectWrapper : ISomeType 
{ 
    Object _someObject; 
    PropertyInfo _valuePropertyInfo; 

    public SomeObjectWrapper(Object wrappedSomeObject) 
    { 
     _someObject = wrappedSomeObject; 
     _valuePropertyInfo = _someObject.GetType().GetProperty("Value", System.Reflection.BindingFlags.Public); 
    } 

    public object Value 
    { 
     get { return _valuePropertyInfo.GetValue(_someObject, null); } 
     set { _valuePropertyInfo.SetValue(_someObject, value, null); } 
    } 
} 
+0

這是一種有效的方法,但如果可能的話,我真的很樂意不使用反射。如果可能的話,我寧願將其混入一個通用界面。 – 2010-11-02 16:03:09

0

編輯使用LinFu的.NET 3.5 您可以使用LinFu而不是Castle。然而,無論如何,你會使用反射,無論是Castle還是Linfu的DynamicProxy,都只能隱藏在庫的內部,而不是暴露在代碼中。因此,如果您的要求避免使用反射是出於性能考慮,那麼使用此解決方案就不會真正避免它。 在這種情況下,我會親自選擇Orsol的解決方案。

但是:這裏有一個LinFu的ducktyping的例子。

public interface ISomeType { 
    object Value{get; set;} 
} 

public class SomeType1 
{ 
    public int Value { get; set; } 
} 

public class SomeType2 
{ 
    public string Value { get; set; } 
} 

public class SomeTypeWrapperFactory 
{ 

    public static ISomeType CreateSomeTypeWrapper(object aSomeType) 
    { 
     return aSomeType.CreateDuck<ISomeType>(); 
    }   
} 


class Program 
{ 
    public static void Main(string[] args) 
    { 
     var someTypes = new object[] { 
      new SomeType1() {Value=1}, 
      new SomeType2() {Value="test"} 
     }; 


     foreach(var o in someTypes) 
     { 
      Console.WriteLine(SomeTypeWrapperFactory.CreateSomeTypeWrapper(o).Value); 
     } 
     Console.ReadLine(); 
    } 
} 

既然你不知道SOMETYPE的,直到運行時,我不會用混入的類型,但訪問者模式(我知道這並沒有回答關於如何使用混入了這個問題,但我只是認爲我會投入我的2美分)。

在.NET 4中使用動態Bradley Grainger's post here使用C#4的動態關鍵字來實現訪問者模式。 在你的情況,閱讀完所有的「價值」從SOMETYPE的字典特性可以工作是這樣的:

public class SomeType1 
{ 
    public int Value { get; set; } 
} 

public class SomeType2 
{ 
    public string Value { get; set; } 
} 

public class SomeTypeVisitor 
{ 
    public void VisitAll(object[] someTypes) 
    { 
     foreach(var o in someTypes) { 
      // this should be in a try-catch block 
      Console.WriteLine(((dynamic) o).Value); 
     } 

    } 
} 
class Program 
{ 
    public static void Main(string[] args) 
    { 
     var someTypes = new object[] { 
      new SomeType1() {Value=1}, 
      new SomeType2() {Value="test"} 
     }; 

     var vis = new SomeTypeVisitor(); 

     vis.VisitAll(someTypes);    
    } 
} 
+0

我無法使用C#4.0。我們的平臺是3.5。 – 2010-11-04 17:53:08

+0

使用LinFu的DuckTyping添加了一個解決方案 – 2010-11-05 09:13:32

相關問題