2009-01-03 117 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