Is it possible to use the generic Wrapper class?

In C # 3.0 and .NET 3.5, imagine an interface:

public interface INameable
{
  string Name {get;}
}

      

and many immutable classes that implement the interface.

I would like to have one extension method

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

      

which returns a wrapped instance of the original object with only the changed name, and all other property reads and method calls are redirected to the original object.

How do I get a generic wrapper class for this without applying it across all INameable implementation types? Do you think this is possible?

+1


source to share


2 answers


No, this is not possible, unless T

it is an interface or a class with all members virtual, and this constraint cannot be specified at compile time (although you could write a runtime check if you are happy with this approach).

The reason you cannot do this for arbitrary types is that if you take an object of the type T

, then you must return an assignable object T

. If I pass in an object that looks like this ...

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

      



... then you can not create another type that can be assigned SomeClass

. Do not use Reflection.Emit

any other method, as the type is sealed.

However, if you're happy with the constraints I mentioned, you can use something like the DynamicProxy framework to create a type that proxies the passed object and intercepts calls for either forwarding or reimplementation as needed.

+3


source


Well, yes, it is possible, but it has to do with in-memory code generation.

You can see Reflection.Emit and here .

Please note that it will contain a lot of code.

That is, if I believe I understand you correctly.



Here's what I think you are asking:

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

      

Is it correct?

+1


source







All Articles