如何将泛型方法限制为具有指定属性的类?

时间:2010-10-06 13:49:24

标签: c# generics attributes

我想创建一个只适用于具有Serializable属性的类的泛型方法,例如

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

但显然上面没有编译。而且我猜我是否将SerializableAttribute放在那里,它会坚持T是属性,而不是具有该属性的类。

你怎么做这样的事情?

3 个答案:

答案 0 :(得分:4)

无法对属性进行约束。一种解决方案可能是使用反射来分析传递给方法的对象,并查看它是否声明了Serializable属性。

答案 1 :(得分:2)

您可以实现ISerializable接口并使用“where T:ISerializable”,但是您必须在每个类中实现ISerializable方法。运行时检查可以在类上查找SerializableAttribute,但是您没有编译时检查。您可以考虑编写自己的接口,这些接口几乎不需要实现,可能只是一个Property并在每个类上实现该接口。有点像...

public interface ISerializableSet {
    bool IsSerializable { get; }
}

您的实现可以使用反射然后进行运行时检查,您的Foo方法将被声明为“where 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]。如果您正在使用单元测试,则可以在测试时检测到问题。

答案 2 :(得分:0)

您必须使该类实现一个接口应用该属性。 然后,您可以通过界面进行过滤:

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