Как ограничить универсальный метод классами с указанным атрибутом? - PullRequest
3 голосов
/ 06 октября 2010

Я хочу создать универсальный метод, который применим только к классам, имеющим атрибут Serializable, например,

public static int Foo<T>(T obj) where T : Serializable {
  ...
}

но, очевидно, вышеприведенное не компилируется. И я предполагаю, что если я поставлю SerializableAttribute, он будет настаивать на том, что T - это атрибут, а не класс с этим атрибутом.

Как ты делаешь что-то подобное?

Ответы [ 3 ]

4 голосов
/ 06 октября 2010

Ограничения на атрибуты не могут быть сделаны. Одним из решений может быть использование отражения для анализа объекта, передаваемого в ваш метод, и проверки наличия объявленного атрибута Serializable.

2 голосов
/ 06 октября 2010

Вы могли бы реализовать интерфейс ISerializable и использовать это "где T: ISerializable", но тогда вам нужно реализовать методы ISerializable в каждом классе. Проверка во время выполнения может искать SerializableAttribute в классе, но тогда у вас нет проверок времени компиляции. Вы можете написать свой собственный интерфейс, который очень мало нужно реализовать, может быть, просто Property и реализовать этот интерфейс в каждом из ваших классов. Что-то вроде ...

public interface ISerializableSet {
    bool IsSerializable { get; }
}

Ваша реализация могла бы использовать отражение, чтобы затем выполнить проверку во время выполнения, ваш метод Foo был бы объявлен «где T: ISerializableSet» для проверки времени компиляции.

Вот более полный пример ...

public interface ISerializableSet
{
    bool IsSerializable { get; }
}

[Serializable]
class SerializableClass : ISerializableSet
{
    [NonSerialized]
    private bool _runTimeCheck = true;

    #region ISerializableSet Members
    public bool IsSerializable
    {
        get { 
            if(!_runTimeCheck)
                return true;
            if(0 != (this.GetType().Attributes & System.Reflection.TypeAttributes.Serializable))
                return true;
            return false;
        }
    }
    #endregion
}

public static class Bar2
{
    public static int Foo<T>(T obj) where T : ISerializableSet
    {
        ISerializableSet sc = obj;
        Console.WriteLine("{0}", sc.IsSerializable.ToString());
        return 1;
    }
}

Вы можете проверить свойство IsSerializable в своем конструкторе и выдать исключение времени выполнения, если кто-то непреднамеренно удалит [Serializable]. Если вы используете модульные тесты, вы можете обнаружить проблемы во время теста.

0 голосов
/ 06 октября 2010

Вы должны заставить эти классы реализовывать интерфейс, применяющий этот атрибут.Затем вы можете фильтровать по интерфейсу:

public static int Foo<T>(T obj) where T : ISerializable
{}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...