将常量作为C#泛型类型参数传递

将常量作为C#泛型类型参数传递,c#,nhibernate,generics,C#,Nhibernate,Generics,我有一个NHibernate IUserType,我正试图使用它将两个固定大小的double[]字段(大小不同)作为blob绑定到单个数据库列。我有下面的代码,但不知何故,我需要传递一个常量整数,以便它知道数组应该有多大。我认为没有一种方法可以在运行时以自定义方式实例化此类型,因此大小确实需要是类型本身的一部分。如果我能避免的话,我宁愿不要这堂课的两本 public class DoubleArrayUserType<Size> : NHibernate.UserTypes.IUse

我有一个NHibernate IUserType,我正试图使用它将两个固定大小的double[]字段(大小不同)作为blob绑定到单个数据库列。我有下面的代码,但不知何故,我需要传递一个常量整数,以便它知道数组应该有多大。我认为没有一种方法可以在运行时以自定义方式实例化此类型,因此大小确实需要是类型本身的一部分。如果我能避免的话,我宁愿不要这堂课的两本

public class DoubleArrayUserType<Size> : NHibernate.UserTypes.IUserType
{
    private int _size = sizeof(Size);

    public object Assemble(object cached, object owner)
    {
        if (cached == null)
            return null;

        if (cached == DBNull.Value)
            return null;

        if (!(cached is byte[]))
            throw new ArgumentException();

        var arrayBytes = cached as byte[];
        var arrayStream = new BinaryReader(new MemoryStream(arrayBytes));

        var values = new double[_size];
        for (int i = 0; i < _size; ++i)
            values[i] = arrayStream.ReadDouble();

        return values;
    }

    public object Disassemble(object value)
    {
        if (value == null)
            return DBNull.Value;

        if (value == DBNull.Value)
            return DBNull.Value;

        if (!(value is double[]))
            throw new ArgumentException();

        var values = value as double[];
        var bytes = new List<byte>(sizeof(double) * _size);
        for (int i = 0; i < _size; ++i)
            bytes.AddRange(BitConverter.GetBytes(values[i]));
        return bytes.ToArray();
    }

    public NHibernate.SqlTypes.SqlType[] SqlTypes
    {
        get { return new NHibernate.SqlTypes.SqlType[] { NHibernate.SqlTypes.SqlTypeFactory.GetBinaryBlob(1) }; }
    }
}
公共类DoubleArrayUserType:NHibernate.UserTypes.IUserType
{
私有int_size=sizeof(size);
公共对象集合(对象缓存,对象所有者)
{
如果(缓存==null)
返回null;
if(cached==DBNull.Value)
返回null;
如果(!(缓存的是字节[])
抛出新ArgumentException();
var arrayBytes=缓存为字节[];
var arrayStream=新的二进制读取器(新的内存流(arrayBytes));
var值=新的双[_大小];
用于(int i=0;i<_size;++i)
值[i]=arrayStream.ReadDouble();
返回值;
}
公共对象(对象值)
{
如果(值==null)
返回DBNull.Value;
if(value==DBNull.value)
返回DBNull.Value;
如果(!(值为双精度[])
抛出新ArgumentException();
var值=作为双[]的值;
var字节=新列表(sizeof(double)*\u大小);
用于(int i=0;i<_size;++i)
bytes.AddRange(BitConverter.GetBytes(值[i]);
返回bytes.ToArray();
}
公共NHibernate.SqlTypes.SqlType[]SqlTypes
{
获取{return new NHibernate.SqlTypes.SqlType[]{NHibernate.SqlTypes.SqlTypeFactory.GetBinaryBlob(1)};}
}
}

这里有一个有争议的解决方案(期望获得否决票!),但它不会产生一个常数。我相信你也能以不同的方式解决你的问题:

public interface IHasSize{
  int Size { get; }
}

public class MySize : IHasSize { 
  public int Size { get { return 4; } }
}

public class RequiresASize<TSize> where TSize : IHasSize, new()
{
  private int _size = new TSize().Size;
}

public class ProvidesASize : RequiresASize<MySize>{
  //_size in base class will be 4
}
公共接口iHissize{
整数大小{get;}
}
公共类MySize:iMassize{
公共整数大小{get{return 4;}}
}
公共类要求大小,其中TSize:iMassize,new()
{
private int_size=new TSize().size;
}
公共类大小:RequiresASize{
//_基类中的大小将为4
}

因此,
RequiresASize
是你问题中的一个大类。最后,我通过
ProvidesASize
类型使用继承来演示它是如何工作的。

这里有一个有争议的解决方案(期望获得否决票!),但它不会产生一个常量。我相信你也能以不同的方式解决你的问题:

public interface IHasSize{
  int Size { get; }
}

public class MySize : IHasSize { 
  public int Size { get { return 4; } }
}

public class RequiresASize<TSize> where TSize : IHasSize, new()
{
  private int _size = new TSize().Size;
}

public class ProvidesASize : RequiresASize<MySize>{
  //_size in base class will be 4
}
公共接口iHissize{
整数大小{get;}
}
公共类MySize:iMassize{
公共整数大小{get{return 4;}}
}
公共类要求大小,其中TSize:iMassize,new()
{
private int_size=new TSize().size;
}
公共类大小:RequiresASize{
//_基类中的大小将为4
}

因此,
RequiresASize
是你问题中的一个大类。最后,我通过
ProvidesASize
类型使用继承来演示它是如何工作的。

我假设您知道问题的内容暗示您想做一些在.Net中不可能的事情?你可能想考虑改变它。为什么你不能把数组字节长度除以两倍的大小?你说你不想要两个丑陋类的拷贝。这是否意味着您只需要两个不同的
\u size
?这两种价值观是什么?也许您可以分别使用
int
long
作为
Size
类型参数?目前,我需要6和8,但这可能会改变。我假设您知道问题的文本意味着您想做一些在.Net中不可能做的事情?你可能想考虑改变它。为什么你不能把数组字节长度除以两倍的大小?你说你不想要两个丑陋类的拷贝。这是否意味着您只需要两个不同的
\u size
?这两种价值观是什么?也许您可以分别使用
int
long
作为
Size
类型参数?目前,我需要6和8,但这可能会改变。您的比我的更详细,但与我的不同,它看起来可以工作P
struct iTRAQArray{readonly double[]values=new double[8];}struct TMTArray{readonly double[]values=new double[6];}公共类iTRAQArrayUserType:DoubleArrayUserType{}公共类TMTArrayUserType:DoubleArrayUserType{}<>代码>我想你可以说这种技术与Boost和“更新”C++代码中使用的整个“类型特征”机制类似。我以前从未想过要这样做,我仍然不完全相信不能用另一种方式来做;但是,如果它真的起作用,那么很乐意提供帮助:)有点奇怪,
RequiresASize
RequiresASize
作为类型是不同的,即使
MySize4
SomeOtherSize4
都通过返回4来实现
Size
属性。您可以为
RequiresASize
编写一个静态构造函数,以检查
TSize
类型永远不是其他人的类。是的,为true-或者您可以将接口设置为内部接口,然后在实现类型需要为公共的情况下使用显式接口实现;虽然我想这完全取决于项目结构。为什么不跳过泛型,只使用具有虚拟大小的DoubleArrayUserType的后代呢?您的比我的要详细一些,但与我的不同,它看起来可以工作P
struct iTRAQArray{readonly double[]values=new double[8];}struct TMTArray{readonly double[]values=new double[6];}公共类iTRAQArrayUserType:DoubleArrayUserType:DoubleArrayUserType{}
I支持