为通用方法参数提供具体类型值

时间:2014-05-30 13:05:30

标签: c# generics parameters

我有一个通用接口,它定义了保护特定值类型的功能。特定的提供程序实现能够保护某些值类型值(即ISecurityProvider<int>字符串(ISecurityProvider<string>)。这就是为什么我将一个通用类型约束放到IConvertible以涵盖两者。

提供者接口定义

public interface ISecurityProvider<TSecurable>
    where TSecurable : IConvertible // to constrain to struct types AND string
{
    TSecurable Secure(TSecurable value);
}

然后我有我的实体类应该能够使用这些提供程序并根据安全提供程序的实现保护自己的属性。

我定义了一个抽象的基本实体类,实际的类继承自

public abstract class BaseEntity
{
    protected bool IsSecured { get; set; }

    protected virtual void SecureSelf<TSecurable>(ISecurityProvider<TSecurable> provider)
        where TSecurable : IConvertible
    {
        if (!this.IsSecured)
        {
            this.IsSecured = true;
        }
    }
}

具有必须受到保护的标识属性的示例实体。

public class SomeDataRecord : BaseEntity
{
    public int Id { get; set; }

    public string Name { get; set; }

    public override void SecureSelf<TSecurable>(ISecurityProvider<TSecurable> provider)
    {
        if (!this.IsSecured)
        {
            base.SecureSelf(provider);
            this.Id = provider.Secure(this.Id); // COMPILER ERROR
        }
    }
}

我得到的错误是:

  

'ISecurityProvider.Secure(TSecurable)'的最佳重载方法匹配有一些无效的参数。

如何调用provider.Secure()方法使其正常工作?

其他信息

基本上我希望我的各个实体类能够保护所有可能属于不同类型的适用属性。在我的示例中,我有一个整数和一个字符串属性。

我的SecureSelf方法应该同时保护所有这些方法,因为它们都依赖于相同的IsSecured属性。所以我的榜样并不是最好的。我可能宁愿为我的SecureSelf方法提供安全提供程序工厂,在内部它应该获取特定的提供程序实例以保护单独类型的属性。或者我认为......

2 个答案:

答案 0 :(得分:2)

考虑到您尝试使用Secure的方式,您应该将约束放在方法上而不是接口上:

public interface ISecurityProvider
{
    TSecurable Secure<TSecurable>(TSecurable value) where TSecurable : IConvertible;
}

public abstract class BaseEntity
{
    protected bool IsSecured { get; set; }

    protected virtual void SecureSelf(ISecurityProvider provider)
    {
        if (!this.IsSecured)
        {
            this.IsSecured = true;
        }
    }
}

public class SomeDataRecord : BaseEntity
{
    public int Id { get; set; }

    public string Name { get; set; }

    protected override void SecureSelf(ISecurityProvider provider)
    {
        if (!this.IsSecured)
        {
            base.SecureSelf(provider);
            this.Id = provider.Secure(this.Id);
        }
    }
}

答案 1 :(得分:0)

你得到了那个例外因为&#34; int&#34;不是&#34; TSecurable&#34;,你可以避免这种情况使BaseEntity变得通用,并且你的特定类继承了具体类型的基础:

public interface ISecurityProvider<TSecurable>
where TSecurable : IConvertible // to constrain to struct types AND string
{
    TSecurable Secure(TSecurable value);
}

public abstract class BaseEntity<TSecurable> where TSecurable : IConvertible
{
    protected bool IsSecured { get; set; }

    protected virtual void SecureSelf(ISecurityProvider<TSecurable> provider)
    {
        if (!this.IsSecured)
        {
            this.IsSecured = true;
        }
    }
}

public class SomeDataRecord : BaseEntity<int>
{
    public int Id { get; set; }

    public string Name { get; set; }

    protected override void SecureSelf(ISecurityProvider<int> provider)
    {
        if (!this.IsSecured)
        {
            base.SecureSelf(provider);
            this.Id = provider.Secure(this.Id); // COMPILER ERROR
        }
    }

}

此外,如果所有内容都是IConvertible,您可以使用非通用方法:

public interface ISecurityProvider
{
    IConvertible Secure(IConvertible value);
}

public abstract class BaseEntity
{
    protected bool IsSecured { get; set; }

    protected virtual void SecureSelf(ISecurityProvider provider)
    {
        if (!this.IsSecured)
        {
            this.IsSecured = true;
        }
    }
}

public class SomeDataRecord : BaseEntity
{
    public int Id { get; set; }

    public string Name { get; set; }

    protected override void SecureSelf(ISecurityProvider provider)
    {
        if (!this.IsSecured)
        {
            base.SecureSelf(provider);
            this.Id = (int)provider.Secure(this.Id);
            this.Name = (string)provider.Secure(this.Name);
        }
    }
}