Any substitute solutions of generic type attributes?
Becase we can't use generic type attributes, are there any substitute solutions? Maybe an example is helpful to discuss:
public abstract class ErrorHandler { }
public class AccessHandler : ErrorHandler { }
public class ConnectionHandler : ErrorHandler { }
public class OtherHandler : ErrorHandler { }
public class CoHandler<T> : Attribute where T : ErrorHandler
{
public T GetHandler()
{
return default(T); // j开发者_如何学Cust an example
}
}
public enum Errors
{
[CoHandler<AccessHandler>()]
Access,
[CoHandler<ConnectionHandler>()]
Connection,
[CoHandler<OtherHandler>()]
Other
}
Well, you may accept type or type name argument in attribute constructor. For example
[CoHandler(typeof(AccessHandler))]
or
[CoHandler("[Fully or partially qualified type name]")]
Former is simpler to use while later is useful when you don't want to take or can't take dependency on the assembly containing the type.
BTW, return default(T);
will always return null, I hope its just for illustration purpose. Here's the example, how you can use type argument:
public class CoHandler : Attribute
{
private Type _Type;
public CoHandler(Type type)
{
_Type = type;
// Use reflection to validate type argument to see if it has
// inherited from ErrorHandler and check if its has parameterless
// constructor
}
public ErrorHandler GetHandler()
{
return (ErrorHandler)Activator.CreateInstance(_Type);
}
}
In your example, by changing the enum into a class, and using interfaces instead of attributes, you could achieve the same functionality.
You could test for interface implementation with as, and you can also write extension methods for the interface.
You can also implement methods on the Errors classes, giving more range than plain old enums.
{
Errors error = Errors.Access;
var handler = error.GetHandler();
}
public abstract class ErrorHandler { }
public class AccessHandler : ErrorHandler { }
public class ConnectionHandler : ErrorHandler { }
public class OtherHandler : ErrorHandler { }
public interface CoHandler<T>
where T : ErrorHandler
{
T GetHandler();
}
public abstract class Errors
{
public static Errors Access = new AccessError();
public static Errors Connection = new ConnectionError();
public abstract ErrorHandler GetHandler();
private class AccessError : Errors, CoHandler<AccessHandler>
{
public override ErrorHandler GetHandler()
{
return new AccessHandler();
}
AccessHandler CoHandler<AccessHandler>.GetHandler()
{
return new AccessHandler();
}
}
private class ConnectionError : Errors, CoHandler<ConnectionHandler>
{
public override ErrorHandler GetHandler()
{
return new ConnectionHandler();
}
ConnectionHandler CoHandler<ConnectionHandler>.GetHandler()
{
return new ConnectionHandler();
}
}
}
精彩评论