Как заменить автоматически реализованное тело C # get во время выполнения или во время компиляции? - PullRequest
4 голосов
/ 17 июня 2010

Я пытался выяснить это всю ночь, но я думаю, что мои знания о .Net Framework не так уж глубоки, и проблема не совсем в Google, но если я смогу кивнуть в правильное направление, я уверен, что смогу реализовать это, так или иначе.

Я бы хотел иметь возможность объявить свойство, украшенное пользовательским атрибутом, следующим образом:

public MyClass {

    [ReplaceWithExpressionFrom(typeof(SomeOtherClass))]
    public virtual bool MyProperty { get; }

}

public SomeOtherClass : IExpressionHolder<MyClass, bool> {

    ...
}

public interface IExpressionHolder<TArg, TResult> {
    Expression<Func<TArg, TResult>> Expression { get; }
}

А потом каким-то образом - это та часть, которую я не могу понять - замените автоматически сгенерированную реализацию этого геттера частью пользовательского кода, что-то вроде:

Type expressionHolderType = LookupAttributeCtorArgTypeInDeclarationOfPropertyWereReplacing();
return ReplaceWithExpressionFromAttribute.GetCompiledExpressionFrom(expressionHolderType)(this);

Главное, я не уверен, как это сделать, это заменить автоматическую реализацию get.

Первое, что пришло на ум, было PostSharp , но это более сложная зависимость, чем я забочусь. Я бы предпочел способ кодировать его без использования постобработки, прикрепленной к сборке (я думаю, в этом и заключается суть того, как PostSharp в любом случае поглощает свои хуки).

Другая часть этого, в которой я не так уверен, заключается в том, как извлечь параметр типа, переданный конкретному экземпляру атрибута ReplaceWithExpressionFrom (где он украшает свойство, тело которого я хочу заменить; другими словами, как сделать Я получаю typeof (SomeOtherClass), где я пишу замену получить тело). Я планирую кэшировать скомпилированные выражения из конкретных экземпляров IExpressionHolder, поскольку я не хочу делать это каждый раз, когда свойство извлекается.

Я полагаю, что это просто получил , чтобы быть возможным. По крайней мере, я полагаю, что я должен быть в состоянии найти сборку для любого метода, украшенного атрибутом, и каким-то образом прокси-классом или просто заменить IL или .. что-то? И я хотел бы сделать интеграцию настолько гладкой, насколько это возможно, поэтому, если это можно сделать без явного вызова метода регистрации или инициализации, который был бы великолепен.

Спасибо!

Ответы [ 2 ]

2 голосов
/ 17 июня 2010

Может быть, я получу понижение за это, но зачем вам недвижимость для этого?

То, что вы хотите, это виртуальный вызов. Почему бы просто не создать подкласс MyClass и реализовать виртуальный вызов?

Или вы можете использовать словарь делегатов для вызова соответствующей функции.

1 голос
/ 22 декабря 2010

Кажется, невозможно заменить реализацию метода во время выполнения.

Его можно заменить во время компиляции, как это делает PostSharp с переписыванием и переплетением IL.

Кроме того, сгенерированный прокси-сервер может переопределять виртуальные члены - хотя для этого требуется создание объекта через централизованную точку, где прокси-серверы могут выдаваться вместо реальных вещей (в стиле NHibernate).

...