RepositoryBase
является не базовым классом MyEntityRepository
. Вы ищете общую дисперсию , которая существует в C # в ограниченной степени, но здесь не применима.
Предположим, что у вашего класса RepositoryBase
был такой метод:
void Add(T entity) { ... }
Теперь рассмотрим:
MyEntityRepository myEntityRepo = GetMyEntityRepo(); // whatever
RepositoryBase baseRepo = (RepositoryBase)myEntityRepo;
baseRepo.Add(new OtherEntity(...));
Теперь вы добавили другой тип сущности в MyEntityRepository
... и это не может быть прав.
В принципе, общая дисперсия является безопасной только в определенных ситуациях. В частности, общая ковариация (именно это вы описываете здесь) безопасна только тогда, когда вы только когда-либо получаете значения «API»; общая контравариантность (которая работает наоборот) безопасна только тогда, когда вы когда-либо вводили значения в API (например, общее сравнение, которое может сравнивать любые две формы по площади, можно рассматривать как сравнение квадратов).
В C # 4 это доступно для общих интерфейсов и общих делегатов, а не для классов - и только для ссылочных типов. См. MSDN для получения дополнительной информации, прочитайте & lt; plug & gt; прочитайте C # в глубине, 2-е издание , глава 13 & lt; / plug & gt; или блога Эрика Липперта по этой теме. Кроме того, я рассказал об этом в NDC в июле 2010 года - видео доступно здесь .
C# не является ориентированным языком AOP. Это имеет некоторые функции AOP, и можно эмулировать некоторых других, но AOP создания с C# является болезненным.
я искал способы сделать точно, что Вы хотели сделать, и я не нашел простого способа сделать это.
Насколько я понимаю, это - то, что Вы хотите сделать:
[Log()]
public void Method1(String name, Int32 value);
и чтобы сделать это, у Вас есть две основных опции
, Наследовали Ваш класс от MarshalByRefObject или ContextBoundObject и определяют атрибут, который наследовался IMessageSink. Эта статья имеет хороший пример. Необходимо рассмотреть nontheless, как который с помощью MarshalByRefObject понизится производительность черт, и я имею в виду его, я говорю о 10x производительность, потерянная, так думайте тщательно прежде, чем попробовать это.
другая опция состоит в том, чтобы ввести код непосредственно. Во времени выполнения имея в виду необходимо будет использовать отражение, чтобы "считать" каждый класс, получить его атрибуты и ввести вызов appropiate (и в этом отношении я думаю, что Вы не могли использовать Отражение. Испустите метод, поскольку я думаю Отражение. Испустите не позволил бы Вам вводить новый код в уже существующем методе). Во время проектирования это будет означать создавать расширение компилятора CLR, который у меня нет честно идеи о том, как это сделано.
заключительная опция использует платформа МОК . Возможно, это не идеальное решение как большинство работ платформ МОК путем определения точек входа, которые позволяют методам быть сцепленными, но, в зависимости от того, что Вы хотите к achive, который мог бы быть справедливым приближением.
Я не знаю решения, но мой подход был бы следующие.
Украшают класс (или его методы) с пользовательским атрибутом. Где-то в другом месте в программе, позвольте инициализации функциональное отражение все типы, прочитайте методы, украшенные атрибутами, и введите некоторый код IL в метод. Это могло бы на самом деле быть более практично к замена метод тупиком, который звонит LogStart
, фактический метод и затем LogEnd
. Кроме того, я не знаю, можно ли изменить методы с помощью отражения, таким образом, это могло бы быть более практично для замены целого типа.
Смотрите на это - Довольно тяжелый материал.. http://msdn.microsoft.com/en-us/magazine/cc164165.aspx
Существенный .net - поле Дона имело главу по тому, что Вам нужен названный Перехват. Я очистил часть его здесь (Извините за цвета шрифта - у меня была темная тема тогда...) http://madcoderspeak.blogspot.com/2005/09/essential-interception-using-contexts.html
Если Вы пишете, что класс - называет его Трассировкой - который реализует интерфейс IDisposable, Вы могли обернуть все тела метода в
Using( Tracing tracing = new Tracing() ){ ... method body ...}
В классе Трассировки, который Вы могли дескриптор логика трассировок в методе конструктора/Располагать, соответственно, в классе Трассировки для отслеживания ввод и выход методов. Таким образом, что:
public class Traced
{
public void Method1(String name, Int32 value) {
using(Tracing tracer = new Tracing())
{
[... method body ...]
}
}
public void Method2(Object object) {
using(Tracing tracer = new Tracing())
{
[... method body ...]
}
}
}
Самый простой способ достигнуть, который должен, вероятно, использовать PostSharp. Это вводит код в Ваших методах на основе атрибутов, что Вы обращаетесь к нему. Это позволяет Вам делать точно, что Вы хотите.
Другая опция состоит в том, чтобы использовать профильный API для введения кода в методе, но это - действительно хардкор.
Вы могли потенциально использовать Шаблон "декоратор" GOF и 'украсить' все классы та трассировка потребности.
Это, вероятно, только действительно практично с контейнером МОК (но как указатель ранее можно хотеть рассмотреть перехват метода, если Вы собираетесь спуститься по пути МОК).
вам нужно проверить Айенде, чтобы узнать, как он это сделал: http://ayende.com/Blog/archive/2009/11/19/can-you-hack-this-out.aspx
GRAILS_OPTIONS
? – Bozho 3 August 2010 в 11:16