Атрибуты .net, которые обрабатывают исключения - использование в методе доступа к свойству - PullRequest
3 голосов
/ 03 апреля 2010

хорошо я знаю из моего опыта работы с asp.net mvc, что у вас могут быть атрибуты, которые обрабатывают исключения (HandleErrorAttribute). Насколько я могу судить, класс Controller имеет некоторое событие OnException, которое может быть неотъемлемой частью этого поведения. Тем не менее, я хочу сделать что-то подобное в моем собственном коде:

пример сна:

public String MyProperty
{
    [ExceptionBehaviour(typeof(FormatException), MyExEnum.ClearValue)]
    set
    {
        _thing.prop = Convert.ToThing(value);
    }
}
....

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

Есть идеи, ребята?

Ответы [ 2 ]

3 голосов
/ 03 апреля 2010

Нет, это невозможно, если вы не используете PostSharp или подобное. Это не стандартная функция атрибута - скорее, ASP.NET MVC добавляет для вас. Вы не получите его для всех атрибутов.

2 голосов
/ 04 апреля 2010

Вы не можете добавить атрибут, и автоматически добавляется код обработки исключений вокруг всех вызовов свойства / метода. То, что вы можете сделать, если вы создаете для этого какую-то платформу, - это посмотреть на атрибуты типа во время выполнения и реализовать свою собственную стратегию.

Например, допустим, у нас был этот атрибут:

public enum ExceptionAction { Throw, ReturnDefault };

[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class ExceptionBehaviorAttribute : Attribute
{
    public ExceptionBehaviorAttribute(Type exceptionType, ExceptionAction action)
    {
        this.exceptionType = exceptionType;
        this.action = action;
    }

    public Type ExceptionType { get; private set; }
    public ExceptionAction Action { get; private set; }
}

И скажем, мы украсили им свойство:

public interface IHasValue
{
    int Value { get; }
}

public class MyClass : IHasValue
{
    private string value;

    public int Value
    {
        [ExceptionBehavior(typeof(FormatException),
            ExceptionAction.ReturnDefault)]
        get { return int.Parse(this.value); }
    }
}

Вы можете написать определенный код, чтобы посмотреть на этот атрибут и реализовать желаемое поведение:

public int GetValue(IHasValue obj)
{
    if (obj == null)
        throw new ArgumentNullException("obj");
    Type t = obj.GetType();
    PropertyInfo pi = t.GetProperty("Value",
        BindingFlags.Instance | BindingFlags.Public);
    MethodInfo getMethod = pi.GetGetMethod();
    var exbAttributes = (ExceptionBehaviorAttribute[])
        getMethod.GetCustomAttributes(typeof(ExceptionBehaviorAttribute), false);
    try
    {
        return obj.Value;
    }
    catch (Exception ex)
    {
        var matchAttribute = exbAttributes.FirstOrDefault(a =>
            a.ExceptionType.IsAssignableFrom(ex.GetType()));
        if ((matchAttribute != null) &&
            (matchAttribute.Action == ExceptionAction.ReturnDefault))
        {
            return default(int);
        }
        throw;
    }
}

Теперь я не говорю, что вы должны сделать это, и это не надежный код, это всего лишь пример того, как вы используете атрибуты. Здесь я пытаюсь продемонстрировать, что (большинство) атрибутов не могут / не изменяют поведение компилятора (это относится и к атрибутам MVC), но вы сможете получить то, что вы хотите если вы специально планируете это. Вы всегда должны будете использовать Отражение, как это.

...