"Dynamic" data type is not the same as native data type

Asked

Viewed 61 times

1

I’m trying to create a struct that has one of its attributes having its type of dynamic or varied data, I need ( when running the struct constructor) to be defined the data type of it, and it should be equal to the native because when I urge it by passing a double for example, this attribute is like the type "Dynamic {double}" and not "double", it has all the functionalities of double but its datatype is "weird", I tried with Object as well and the same thing happens "Object{double}" instead of "double"

I need it to be native because I need to write an array of this struct in an hdf5 file, which cannot write being a non-native type

My struct:

struct opcSt
{
  public Int64 dt;
  public Int64 qlt;
  public dynamic vl;

  public opcSt(Int64 i, Int64 q, dynamic v)
  {
    dt = i;
    qlt = q;
    vl = v;        
  }

  public H5T.H5Type TypetoHDF5Type()
  {
    if (vl.GetType() == typeof(int))
    {
      return H5T.H5Type.NATIVE_INT;
    }
    if (vl.GetType() == typeof(Int64))
    {
      return H5T.H5Type.NATIVE_LONG;
    }
    if (vl.GetType() == typeof(float))
    {
      return H5T.H5Type.NATIVE_FLOAT;
    }
    if (vl.GetType() == typeof(double))
    {
      return H5T.H5Type.NATIVE_DOUBLE;
    }
    else { return H5T.H5Type.C_S1; }
  }
}

Here’s the part where I put in my code the struct that was created

foreach (Opc.Ua.DataValue dv in HistoryReadEnu(m_session, details, bvnodeId))
    {

      var aux = new opcSt((Int64)dv.SourceTimestamp.Subtract(new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds, dv.StatusCode.Code, dv.Value);

      arrayaux.Add(aux);
    }

I need a way to return the raw type (native) double or whatever, float, int, whatever I passed in the construction

Here’s an image I got during debugging, which exemplifies exactly what I’m reporting

inserir a descrição da imagem aqui

  • I’m not sure what the problem is. I even think I understand what you want to do and I have doubts if you should do so, including because the code is unreadable by C#. What is this Opc.Ua.DataValue, how is it composed? Anyway it is almost certain that even need it, almost should never use dynamic and it’s rare enough to need object.

  • i need to instantiate my "opcSt" struct, which is described up there, this datavalue returns a double, in the case that wanted to instantiate my "opcSt" struct by passing a double instead of "Vl", the type of the same would change from "Dynamic" to "double" however, C# converts this to a very strange type that is "Dynamic {double}" and not just "double" and so is my method that writes these records to a file (which only recognizes the primitive types of data) when receiving an "Object{double}" locks and plays an Exception saying it does not recognize this kind of data

  • An example of a way that I will try to circumvent now, creating a struct for the most used types that I will have and after taking the datavalue I instate an array of objects of that struct

  • You kind of repeated what was already written, it still doesn’t make sense to me, but it might not. Or it’s just not clear what the real problem is. This is probably just wrong architecture.

1 answer

-1


I ended up generating specific structs for each type of variable I would need, because to generate the HDF5 file it was necessary to allocate a specific space for each type, so I chose to make a generic class (a helper) and then instantiate the flow I needed based on the kind of data I read:

public class OpcToHdfHelper
  {
    public dynamic opcToRun;
    public void SetTypeAndWriteHdf(string bvtag, IOpcUaSession uaSession, Opc.Ua.ReadRawModifiedDetails readDetails,
                                   Opc.Ua.NodeId sourceId, H5GroupId group)
    {
       var data = HistoryReadEnu(uaSession, readDetails, sourceId);
      int i = 0;
      var p = data.ToArray()[i].Value;
      i = 1;
      while (p == null && i < 10)
  {

    p = data.ToArray()[i].Value;
    i++;
  } ;


  if (p.GetType() == typeof(int))
  {
    opcToRun = new OpcInt32(data, bvtag, group);
  }
  if (p.GetType() == typeof(Int64))
  {
    opcToRun = new OpcInt64();
  }
  if (p.GetType() == typeof(float))
  {
    opcToRun = new OpcFloat();
  }
  if (p.GetType() == typeof(double))
  {
    opcToRun = new OpcDouble(data, bvtag, group);
  }
  if(p.GetType() == typeof(string))
  {
    opcToRun = new OpcString(data, bvtag, group);
  }
  if(p.GetType() == typeof(bool))
  {
    opcToRun = new OpcBoolean(data, bvtag, group);
  }
}

Edit to clarify why different structs were needed:

  struct OpcString
  {
    public Int64 dt;
    public Int64 qlt;
    public IntPtr vl;

    public OpcString(Int64 timestamp = 0, Int64 quality = 0, string value="0")
    {
      dt = timestamp;
      qlt = quality;
      vl = new IntPtr();
      vl = ConvertTo(value);
    }

    IntPtr ConvertTo(string s)
    {
      var x = Marshal.StringToHGlobalAnsi(s);
      return x;
    }

    public OpcString(IEnumerable<Opc.Ua.DataValue> dados, string bvTag, H5GroupId groupId)
{
  dt = 0;
  qlt = 0;
  vl = new IntPtr();
  GenerateHdf5(dados, bvTag, groupId);
}
public void GenerateHdf5(IEnumerable<Opc.Ua.DataValue> dados, string bvTag, H5GroupId groupId)
{
  long[] dims = new long[1];
  dims[0] = dados.Count<Opc.Ua.DataValue>();
  H5DataSpaceId dataSpaceId = H5S.create_simple(1, dims);

  string auxLen = "";
  foreach(Opc.Ua.DataValue vc in dados)
  {
    if (vc.Value != null) { 
    if(vc.Value.ToString().Length > auxLen.Length)
    {
      auxLen = vc.Value.ToString();
    }
    }
  }



  H5DataTypeId stringTypeId = H5T.create(H5T.CreateClass.STRING, -1);


  OpcString opcHelper = new OpcString();

  H5DataTypeId dataTypeId = H5T.create(H5T.CreateClass.COMPOUND, Marshal.SizeOf(opcHelper));
  H5T.insert(dataTypeId, "Timestamp", 0, new H5DataTypeId(H5T.H5Type.NATIVE_LONG));
  H5T.insert(dataTypeId, "Quality", 8, new H5DataTypeId(H5T.H5Type.NATIVE_LONG));
  H5T.insert(dataTypeId, "Value", 16, stringTypeId);


  var list = new List<OpcString>();
  foreach (Opc.Ua.DataValue dv in dados)
  {
    string t = "NullValue";
    if(dv.Value != null)
    {
      t = dv.Value.ToString();
    }
    OpcString aux = new OpcString((Int64)dv.SourceTimestamp.Subtract(new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds, dv.StatusCode.Code, t);
    list.Add(aux);
  }
  H5DataSetId bvDset = H5D.create(groupId, bvTag, dataTypeId, dataSpaceId);
  H5D.write(bvDset, dataTypeId, new H5Array<OpcString>(list.ToArray()));

  H5D.close(bvDset);
  H5S.close(dataSpaceId);

    }
  }
  struct OpcBoolean



 {
    public Int64 dt;
    public Int64 qlt;
    public bool vl;

    public OpcBoolean(Int64 timestamp = 0, Int64 quality = 0, bool value = false)
    {
      dt = timestamp;
      qlt = quality;
      vl = value;
    }


    public OpcBoolean(IEnumerable<Opc.Ua.DataValue> dados, string bvTag, H5GroupId groupId)
    {
      dt = 0;
      qlt = 0;
      vl = false;
      GenerateHdf5(dados, bvTag, groupId);
    }
    public void GenerateHdf5(IEnumerable<Opc.Ua.DataValue> dados, string bvTag, H5GroupId groupId)
    {
  long[] dims = new long[1];
  dims[0] = dados.Count<Opc.Ua.DataValue>();
  H5DataSpaceId dataSpaceId = H5S.create_simple(1, dims);




  OpcBoolean opcHelper = new OpcBoolean();

  H5DataTypeId dataTypeId = H5T.create(H5T.CreateClass.COMPOUND, Marshal.SizeOf(opcHelper));
  H5T.insert(dataTypeId, "Timestamp", 0, new H5DataTypeId(H5T.H5Type.NATIVE_LONG));
  H5T.insert(dataTypeId, "Quality", 8, new H5DataTypeId(H5T.H5Type.NATIVE_LONG));
  H5T.insert(dataTypeId, "Value", 16, new H5DataTypeId(H5T.H5Type.NATIVE_HBOOL));



  var list = new List<OpcBoolean>();
  foreach (Opc.Ua.DataValue dv in dados)
  {
    OpcBoolean aux = new OpcBoolean((Int64)dv.SourceTimestamp.Subtract(new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds, dv.StatusCode.Code, Convert.ToBoolean(dv.Value));
    list.Add(aux);
  }
  H5DataSetId bvDset = H5D.create(groupId, bvTag, dataTypeId, dataSpaceId);
  H5D.write(bvDset, dataTypeId, new H5Array<OpcBoolean>(list.ToArray()));

  H5D.close(bvDset);
  H5S.close(dataSpaceId);

}
  }
  • Have you ever heard of Generics? https://docs.microsoft.com/pt-br/dotnet/csharp/programming-guide/generics/

  • I heard yes but I could not implement in a way that fits well in my situation, my structs had methods that depended on the data titpo in which I was passing, I will put an Edit there to show

Browser other questions tagged

You are not signed in. Login or sign up in order to post.