2009-01-03 57 views
1

在C#3.0和.NET 3.5,想象有一個接口:通用包裝類可能嗎?

public interface INameable 
{ 
    string Name {get;} 
} 

,並實現該接口許多一成不變的類。

我想有一個擴展方法

public static T Rename<T>(this T obj) where T : INameable 
{ 
    ... 
} 

返回原始對象的一個​​包裝實例與剛剛更改了名字和所有其他屬性的讀取和發送到原來的對象方法調用。

如何爲此獲取通用包裝類,而不是爲所有可實現的實現類型實現它?你認爲這是可能的嗎?

回答

3

不,這是不可能的,除非T被限制爲一個接口或者是一個所有成員都是虛擬的類,並且這個約束在編譯時無法指定(儘管您可以編寫一個運行時檢查如果你對這種方法感到滿意)。

您無法爲任意類型執行此操作的原因是,如果您採用T類型的對象,則必須返回可分配給T的對象。如果我傳遞一個對象,看起來如下...

public sealed class SomeClass : INameable 
{ 
    public string Name { get; } 
    public string Abc { get; } 
} 

...那麼有沒有辦法可以創建另一種類型的可分配給SomeClass。不使用Reflection.Emit或任何其他方法,因爲類型是密封的。但是,如果您對我提到的限制感到滿意,那麼您可以使用類似Castle DynamicProxy框架的類來創建一個代理傳入的對象的類型,並截取調用以轉發或重新實現作爲適當的。

+1

看起來像Castle DynamicProxy和LinFu正是我所需要的。我希望C#將在未來提供這種功能。 – Rauhotz 2009-01-03 18:28:33

1

嗯,是的,這是可能的,但它涉及在內存中生成代碼。

您可以查看Reflection.Emithere

請注意,它會涉及很多代碼。

也就是說,如果我假設我正確理解你。

這裏是你問我想什麼:

SomeNameableObject a1 = new SomeNameableObject("ThisIsTheFirstName"); 
SomeNameableObject a2 = a1.Rename("ThisIsTheSecondName"); 
// a1 works, still has the name ThisIsTheFirstName 
// a2 works, but everything is routed to a1, 
// except for the name, which is ThisIsTheSecondName 

是正確的?

+1

是的,這就是我需要的,但我擔心有人提出Reflection.Emit :-) – Rauhotz 2009-01-03 18:09:40