C# 是否有泛型类型属性的替代解决方案?

C# 是否有泛型类型属性的替代解决方案?,c#,.net,generics,attributes,C#,.net,Generics,Attributes,因为,有什么替代方案吗?也许举个例子有助于讨论: public abstract class ErrorHandler { } public class AccessHandler : ErrorHandler { } public class ConnectionHandler : ErrorHandler { } public class OtherHandler : ErrorHandler { } public class CoHandler<T> : Attribute

因为,有什么替代方案吗?也许举个例子有助于讨论:

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);  // just an example
    }

}
public enum Errors
{
    [CoHandler<AccessHandler>()]
    Access,
    [CoHandler<ConnectionHandler>()]
    Connection,
    [CoHandler<OtherHandler>()]
    Other
}
公共抽象类错误处理程序{}
公共类AccessHandler:ErrorHandler{}
公共类ConnectionHandler:ErrorHandler{}
公共类OtherHandler:ErrorHandler{}
公共类CoHandler:属性,其中T:ErrorHandler
{
公共T GetHandler()
{
返回默认值(T);//只是一个例子
}
}
公共枚举错误
{
[CoHandler()]
通道
[CoHandler()]
联系
[CoHandler()]
另外
}

好吧,您可以接受属性构造函数中的type或type name参数。比如说

[CoHandler(typeof(AccessHandler))]

前者使用起来更简单,而当您不想或不能依赖于包含类型的程序集时,后者很有用

顺便说一句,
返回默认值(T)
将始终返回null,我希望它只是为了说明。以下是如何使用类型参数的示例:

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);
    }

}

您可以在属性构造函数中接受类型或类型名参数。比如说

[CoHandler(typeof(AccessHandler))]

前者使用起来更简单,而当您不想或不能依赖于包含类型的程序集时,后者很有用

顺便说一句,
返回默认值(T)
将始终返回null,我希望它只是为了说明。以下是如何使用类型参数的示例:

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);
    }

}

在您的示例中,通过将枚举更改为类,并使用接口而不是属性,可以实现相同的功能

您可以使用as测试接口实现,还可以为接口编写扩展方法

您还可以在Errors类上实现方法,提供比普通旧枚举更多的范围

{
    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();
        }
    }

}
{
Errors=Errors.Access;
var handler=error.GetHandler();
}
公共抽象类ErrorHandler{}
公共类AccessHandler:ErrorHandler{}
公共类ConnectionHandler:ErrorHandler{}
公共类OtherHandler:ErrorHandler{}
公共接口协处理器
其中T:ErrorHandler
{
T GetHandler();
}
公共抽象类错误
{
public static Errors Access=new AccessError();
public static Errors Connection=new ConnectionError();
公共抽象ErrorHandler GetHandler();
私有类访问错误:错误,共句柄
{
公共重写ErrorHandler GetHandler()
{
返回新的AccessHandler();
}
AccessHandler CoHandler.GetHandler()
{
返回新的AccessHandler();
}
}
私有类ConnectionError:错误,共同句柄
{
公共重写ErrorHandler GetHandler()
{
返回新的ConnectionHandler();
}
ConnectionHandler CoHandler.GetHandler()
{
返回新的ConnectionHandler();
}
}
}

在您的示例中,通过将枚举更改为类,并使用接口而不是属性,可以实现相同的功能

您可以使用as测试接口实现,还可以为接口编写扩展方法

您还可以在Errors类上实现方法,提供比普通旧枚举更多的范围

{
    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();
        }
    }

}
{
Errors=Errors.Access;
var handler=error.GetHandler();
}
公共抽象类ErrorHandler{}
公共类AccessHandler:ErrorHandler{}
公共类ConnectionHandler:ErrorHandler{}
公共类OtherHandler:ErrorHandler{}
公共接口协处理器
其中T:ErrorHandler
{
T GetHandler();
}
公共抽象类错误
{
public static Errors Access=new AccessError();
public static Errors Connection=new ConnectionError();
公共抽象ErrorHandler GetHandler();
私有类访问错误:错误,共句柄
{
公共重写ErrorHandler GetHandler()
{
返回新的AccessHandler();
}
AccessHandler CoHandler.GetHandler()
{
返回新的AccessHandler();
}
}
私有类ConnectionError:错误,共同句柄
{
公共重写ErrorHandler GetHandler()
{
返回新的ConnectionHandler();
}
ConnectionHandler CoHandler.GetHandler()
{
返回新的ConnectionHandler();
}
}
}

但我将丢失
where T:ErrorHandler
检查,对吗?有没有办法保持编译时检查?@Danny-是的,没错。您不能让编译器执行此检查。您可以使用静态分析工具(如FxCop)进行编译/构建时检查,然后编写自定义规则,但在我看来,这太麻烦了,您很可能会在第一轮测试中发现不正确的类型用法。但我将丢失
where T:ErrorHandler
检查,对吗?有没有办法保持编译时检查?@Danny-是的,没错。您不能让编译器执行此检查。您可以使用静态分析工具(如FxCop)进行编译/构建时检查,然后编写自定义规则,但在我看来,这太麻烦了,您很可能会在第一轮测试中发现错误的类型用法。与上面的其他答案相比,这是最好的方法。与上面的其他答案相比,这是最好的方法。