Общий класс Wrapper возможен? - PullRequest
1 голос
/ 03 января 2009

В 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 ]

3 голосов
/ 03 января 2009

Нет, это невозможно, если только T не ограничен в качестве интерфейса или класса со всеми виртуальными членами, и это ограничение невозможно указать во время компиляции (хотя вы могли бы написать среду выполнения проверьте, довольны ли вы этим подходом).

Причина, по которой вы не можете сделать это для произвольных типов, заключается в том, что если вы берете объект типа T, вы должны вернуть объект, который может быть назначен на T. Если я передам объект, который выглядит следующим образом ...

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

... тогда вы не сможете создать другой тип, который можно назначить на SomeClass. Не используется Reflection.Emit или любой другой метод, потому что тип запечатан.

Однако, если вы удовлетворены упомянутыми мною ограничениями, вы можете использовать что-то вроде инфраструктуры Castle DynamicProxy для создания типа, который проксирует переданный объект и перехватывает вызовы для пересылки или повторной реализации как необходимо.

1 голос
/ 03 января 2009

Ну, да, это возможно, но это включает генерацию кода в памяти.

Вы можете посмотреть на Reflection.Emit и здесь .

Обратите внимание, что в нем будет много кода.

То есть, если я предполагаю, что правильно вас понимаю.

Вот что, по-моему, вы просите:

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

Это правильно?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...