Канонический шаблон создания Custom Exception с параметром
От: Аноним Ниоткуда  
Дата: 11.09.14 14:49
Оценка:
Часто приходится создавать свои исключения с параметром. Операция однотипная, делается по шаблону. По этому хотелось бы иметь максимально приближенный к стандартам шаблон с учетом всех нюансов.

Вот что нашлось: http://stackoverflow.com/questions/94488/what-is-the-correct-way-to-make-a-custom-net-exception-serializable

 [Serializable]
    // Important: This attribute is NOT inherited from Exception, and MUST be specified 
    // otherwise serialization will fail with a SerializationException stating that
    // "Type X in Assembly Y is not marked as serializable."
    public class SerializableExceptionWithCustomProperties : Exception
    {
        private readonly string resourceName;
        private readonly IList<string> validationErrors;

        public SerializableExceptionWithCustomProperties()
        {
        }

        public SerializableExceptionWithCustomProperties(string message) 
            : base(message)
        {
        }

        public SerializableExceptionWithCustomProperties(string message, Exception innerException)
            : base(message, innerException)
        {
        }

        public SerializableExceptionWithCustomProperties(string message, string resourceName, IList<string> validationErrors)
            : base(message)
        {
            this.resourceName = resourceName;
            this.validationErrors = validationErrors;
        }

        public SerializableExceptionWithCustomProperties(string message, string resourceName, IList<string> validationErrors, Exception innerException)
            : base(message, innerException)
        {
            this.resourceName = resourceName;
            this.validationErrors = validationErrors;
        }

        [SecurityPermissionAttribute(SecurityAction.Demand, SerializationFormatter = true)]
        // Constructor should be protected for unsealed classes, private for sealed classes.
        // (The Serializer invokes this constructor through reflection, so it can be private)
        protected SerializableExceptionWithCustomProperties(SerializationInfo info, StreamingContext context)
            : base(info, context)
        {
            this.resourceName = info.GetString("ResourceName");
            this.validationErrors = (IList<string>)info.GetValue("ValidationErrors", typeof(IList<string>));
        }

        public string ResourceName
        {
            get { return this.resourceName; }
        }

        public IList<string> ValidationErrors
        {
            get { return this.validationErrors; }
        }

        [SecurityPermissionAttribute(SecurityAction.Demand, SerializationFormatter = true)]
        public override void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            if (info == null)
            {
                throw new ArgumentNullException("info");
            }

            info.AddValue("ResourceName", this.ResourceName);

            // Note: if "List<T>" isn't serializable you may need to work out another
            //       method of adding your list, this is just for show...
            info.AddValue("ValidationErrors", this.ValidationErrors, typeof(IList<string>));

            // MUST call through to the base class to let it save its own state
            base.GetObjectData(info, context);
        }
    }


Еще рекомендуют добавлять атрибут ComVisible(true) для класса.

И не ясно зачем [SecurityPermissionAttribute(SecurityAction.Demand, SerializationFormatter = true)]? Насколько это правильно? Посмотрел базовые классы .Net -- в ArgumentException стоит атрибут SecurityCritical на GetObjectData, но никакого на конструкторе SerializationInfo info, StreamingContext context.

Хотелось бы иметь правильный на 100% шаблон. Какие атрибуты нужно проставлять, как в примере или как в системной библиотеке?
Re: Канонический шаблон создания Custom Exception с параметром
От: hardcase Пират http://nemerle.org
Дата: 11.09.14 15:20
Оценка: +1
Здравствуйте, Аноним, Вы писали:

А>Часто приходится создавать свои исключения с параметром. Операция однотипная, делается по шаблону.


С другой стороны, какой смысл в том, чтобы делать все исключения сериализуемыми?
/* иЗвиНите зА неРовнЫй поЧерК */
Re[2]: Канонический шаблон создания Custom Exception с параметром
От: Аноним Ниоткуда  
Дата: 11.09.14 15:49
Оценка: +1
Здравствуйте, hardcase, Вы писали:

H>С другой стороны, какой смысл в том, чтобы делать все исключения сериализуемыми?


Если есть вероятность, что вашу библиотеку будут вызывать удаленно через WCF -- то нужно делать все.

Если не ошибаюсь, то по стандарту все кастомные исключения должны быть сериализуемыми.
Re: Канонический шаблон создания Custom Exception с параметром
От: QrystaL Украина  
Дата: 11.09.14 16:38
Оценка: +1
Здравствуйте, Аноним, Вы писали:

А>
А> [Serializable]
А>    public class SerializableExceptionWithCustomProperties : Exception
А>    {
А>        private readonly string resourceName;
А>        private readonly IList<string> validationErrors;
А>        //...
А>    }
А>


Можно обойтись свойством Data вместо явного объявления полей.
Re[3]: Канонический шаблон создания Custom Exception с параметром
От: hardcase Пират http://nemerle.org
Дата: 11.09.14 21:41
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Если есть вероятность, что вашу библиотеку будут вызывать удаленно через WCF -- то нужно делать все.


Какой смысл вызывающей стороне вообще видеть внутренние исключения сервера?
/* иЗвиНите зА неРовнЫй поЧерК */
Re[4]: Канонический шаблон создания Custom Exception с параметром
От: Shmj Ниоткуда  
Дата: 12.09.14 09:46
Оценка: +2
Здравствуйте, hardcase, Вы писали:

H>Какой смысл вызывающей стороне вообще видеть внутренние исключения сервера?


Почему сразу сервера? Возможно загружают в отдельный AppDomain и оттуда просачивается исключение.
Re[3]: Канонический шаблон создания Custom Exception с параметром
От: SergeyT. США http://sergeyteplyakov.blogspot.com/
Дата: 12.09.14 16:27
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, hardcase, Вы писали:


H>>С другой стороны, какой смысл в том, чтобы делать все исключения сериализуемыми?

+1!

А>Если есть вероятность, что вашу библиотеку будут вызывать удаленно через WCF -- то нужно делать все.


-1! По умолчанию, исключения не могут покидать границы сервиса вообще, но даже если вы захотите это сделать, то стандартные исключения через границу WCF все равно не пролезут.
Тут куча проблем: WCF — это SOA, а значит исключения метода являются частью сигнатуры и должны четко специфицироваться с помощью FaultContract-а. Во-вторых, исключения по своей природе полиморфные и могут содержать члены любых типов (objects, IList, etc), а по умаолчанию стандартный сериализатор (DataContractSerializer) просто их не пережует и рухнет с ошибкой. Подробнее см. в статье на кывте — Известные типы (Known Types) в WCF
Автор: Сергей Тепляков
Дата: 28.02.10
.

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

А>Если не ошибаюсь, то по стандарту все кастомные исключения должны быть сериализуемыми.


По этому же стандарту (речь же про Framework Design Guidelines, верно) нужно просто Avoid создавать свои собственные исключения и делать это лишь тогда, когда вы понимаете, как оно поможет в определенных сценариях восстановления.

В общем, я лично не делаю исключения сериализируемыми, поскольку это захламляет код, а пользы от этого практически никакой, ибо необходимость в их сериализации — это corner case, который я покрою лишь в случае четкой необходимости.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.