在C#3.0和.NET 3.5上,想象一下有一个界面:
public interface INameable
{
string Name {get;}
}
以及许多实现该接口的不可变类。
我想有一个扩展方法
public static T Rename<T>(this T obj) where T : INameable
{
...
}
返回原始对象的包装实例,只更改名称,并将所有其他属性读取和方法调用路由到原始对象。
如何为此获取通用包装类,而不是为所有INameable实现类型实现它?你觉得这可能吗?
答案 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.Emit和here。
请注意,它将涉及大量代码。
也就是说,如果我认为我理解正确的话。
以下是我认为你要求的内容:
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
这是对的吗?