Вы можете достичь этого с помощью функции Перехват контейнера DI, такого как Castle Windsor . Действительно, можно сконфигурировать контейнер таким образом, чтобы все классы, у которых есть метод, украшенный определенным атрибутом, были перехвачены.
Что касается пункта № 3, OP попросил решение без рамки AOP. Я предположил в следующем ответе, что следует избегать: Aspect, JointPoint, PointCut и т. Д. Согласно документации перехвата от CastleWindsor , ни один из них не требуется для выполнения того, что задано.
public class RequireInterception : IContributeComponentModelConstruction
{
public void ProcessModel(IKernel kernel, ComponentModel model)
{
if (HasAMethodDecoratedByLoggingAttribute(model.Implementation))
{
model.Interceptors.Add(new InterceptorReference(typeof(ConsoleLoggingInterceptor)));
model.Interceptors.Add(new InterceptorReference(typeof(NLogInterceptor)));
}
}
private bool HasAMethodDecoratedByLoggingAttribute(Type implementation)
{
foreach (var memberInfo in implementation.GetMembers())
{
var attribute = memberInfo.GetCustomAttributes(typeof(LogAttribute)).FirstOrDefault() as LogAttribute;
if (attribute != null)
{
return true;
}
}
return false;
}
}
container.Kernel.ComponentModelBuilder.AddContributor(new RequireInterception());
public class ConsoleLoggingInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
Console.Writeline("Log before executing");
invocation.Proceed();
Console.Writeline("Log after executing");
}
}
public class Traced
{
[Log]
public void Method1(String name, Int32 value) { }
[Log]
public void Method2(Object object) { }
}
Обратите внимание, что некоторая обработка атрибута потребуется, если только какой-либо метод класса необходимо перехватить. По умолчанию все общедоступные методы будут перехвачены.
Думаю, я бы сделал это так же просто, как:
public static int safeLongToInt(long l) {
if (l < Integer.MIN_VALUE || l > Integer.MAX_VALUE) {
throw new IllegalArgumentException
(l + " cannot be cast to int without changing its value.");
}
return (int) l;
}
Я думаю, что это выражает намерение более ясно, чем повторное использование ... но это несколько субъективно.
Примечание о потенциале интерес - в C # это будет просто:
return checked ((int) l);
Я утверждаю, что очевидный способ увидеть, изменило ли значение при приведении значения, было бы приведение и проверка результата. Однако я бы удалил ненужное приведение при сравнении. Мне также не очень нравятся однобуквенные имена переменных (исключение x
и y
, но не тогда, когда они означают строку и столбец (иногда соответственно)).
public static int intValue(long value) {
int valueInt = (int)value;
if (valueInt != value) {
throw new IllegalArgumentException(
"The long value "+value+" is not within range of the int type"
);
}
return valueInt;
}
Однако на самом деле Я бы хотел избежать этого преобразования, если это вообще возможно. Очевидно, иногда это невозможно,
Целочисленные типы Java представлены со знаком. При вводе между 2 31 и 2 32 (или -2 31 и -2 32 ) приведение будет успешным, но ваш тест потерпит неудачу.
Что нужно проверить, так это то, все ли старшие биты long
одинаковы:
public static final long LONG_HIGH_BITS = 0xFFFFFFFF80000000L;
public static int safeLongToInt(long l) {
if ((l & LONG_HIGH_BITS) == 0 || (l & LONG_HIGH_BITS) == LONG_HIGH_BITS) {
return (int) l;
} else {
throw new IllegalArgumentException("...");
}
}