How do you restrict a generic method to classes with a specified attribute?
I want to create a generic method that is o开发者_如何转开发nly applicable to classes that have the Serializable
attribute, e.g.
public static int Foo<T>(T obj) where T : Serializable {
...
}
but obviously the above doesn't compile. And I'm guessing if I put SerializableAttribute
there, it'll insist that T
is an attribute, not a class with that attribute.
How do you do something like this?
Constraints on attributes cannot be done. One solution could be to use reflection to analyse the object being passed to your method and see if it has the Serializable
attribute declared.
You could implement the ISerializable interface and use that "where T : ISerializable" but then you have to implement the ISerializable methods in every class. A run-time check can look for the SerializableAttribute on the class, but then you don't have compile time checks. You could consider writing your own interface that has very little to have to implement, maybe just a Property and implement that interface on each of your classes. Something like...
public interface ISerializableSet {
bool IsSerializable { get; }
}
Your implementation could use reflection then to do a run-time check, your Foo method would be declared "where T : ISerializableSet" for your compile time check.
Here is a more complete example...
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;
}
}
You could test the IsSerializable property in your constructor and throw a run-time exception in case someone removes [Serializable] inadvertantly. If you are using Unit Tests, you can detect problems at test time.
You must make that classes implement an interface applies that attribute. You may then filter by the interface:
public static int Foo<T>(T obj) where T : ISerializable
{}
精彩评论