2012-07-31 184 views
0

我有一个NHibernate的IUserType,我试图用来将一些固定大小的double []字段(不同大小)绑定到单个数据库列作为BLOB。我有下面的代码,但不知何故,我需要传递一个常量整数,所以它知道数组应该是多大。我不认为有一种方法可以在运行时以自定义的方式实例化这种类型,所以尺寸真的需要成为类型本身的一部分。如果我能避免它,我宁愿没有这个丑陋类的两个副本!传递一个常量作为C#泛型类型参数

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

我假设你意识到你的问题的文字暗示你想要做一些在.Net中不可能的事情?你可能想考虑改变它。 – 2012-07-31 15:00:24

+3

你不能:它不是C++ ;-) – Seb 2012-07-31 15:00:58

+0

有没有理由不能将arrayBytes的长度除以double的大小? – Neil 2012-07-31 15:02:49

回答

6

这是一个有争议的解决方案(期待downvotes!),但它并没有产生一个常数。我敢肯定,你将能够解决您的问题以不同的方式,以及:

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 
} 

所以RequiresASize<TSize>是在你的问题你的大课。我在最后通过ProvidesASize类型使用继承来演示它如何工作。

+0

你比我的详细一点,但不像我的,它看起来像它会工作。 :P 'struct iTRAQArray {readonly double [] values = new double [8]; }结构TMTArray {只读double [] values = new double [6];} struct TMTArray {readonly double [] values = new double [6]; } 公共类iTRAQArrayUserType:DoubleArrayUserType {} 公共类TMTArrayUserType:DoubleArrayUserType {}' – 2012-07-31 15:15:45

+0

我想你可以说这个技术类似于在升压的确“新” C++代码中使用的整个“型特征”的机制。我从来没有想过要这样做,我还没有完全相信它不能以另一种方式完成;但是如果它工作,那么很高兴帮助:) – 2012-07-31 15:22:26

+0

即使'MySize4'和'SomeOtherSize4'通过返回来实现Size属性,'RequiresASize '和'RequiresASize '的类型也不同4.你可以为'RequiresASize '编写一个静态构造函数来检查'TSize'类型是否永远不是别人的类。 – 2012-07-31 15:31:17