通用包装类可能吗?

时间:2009-01-03 17:46:15

标签: c#-3.0

在C#3.0和.NET 3.5上,想象一下有一个界面:

public interface INameable
{
  string Name {get;}
}

以及许多实现该接口的不可变类。

我想有一个扩展方法

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

返回原始对象的包装实例,只更改名称,并将所有其他属性读取和方法调用路由到原始对象。

如何为此获取通用包装类,而不是为所有INameable实现类型实现它?你觉得这可能吗?

2 个答案:

答案 0 :(得分:3)

不可以,这是不可能的,除非T被约束为一个接口或者是一个所有成员都是虚拟的类,并且这个约束不能在编译时指定(尽管你可以写运行时检查你是否对这种方法感到满意。)

您无法对任意类型执行此操作的原因是,如果您使用类型为T的对象,则必须返回可分配给T的对象。如果我传递一个看起来如下的对象.​​.....

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

...那么你无法创建另一种可分配给SomeClass的类型。不使用Reflection.Emit或任何其他方法,因为类型是密封的。

但是,如果您对我提到的限制感到满意,那么您可以使用类似Castle DynamicProxy框架的内容来创建代理传入对象的类型,并拦截调用转发或重新实现为合适的。

答案 1 :(得分: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

这是对的吗?