C#为MarshalAs属性类定义自定义UnmanagedType

Jue*_*gen 1 c# unmanaged marshalling unix-timestamp

是否可以为MarshalAs属性类定义自定义UnmanagedType?具体来说,我想将long int unix时间转换为DateTime类型.像这样的东西:

[MarshalAs(UnmanagedType.LongTimeUnix)]
public DateTime Time;
Run Code Online (Sandbox Code Playgroud)

我在哪里放置自定义LongTimeUnix枚举类型以及放置时间转换代码的位置:

public static DateTime ConvertUnix2DateTime(long timeStamp)
{
        DateTime DT = new DateTime(1970, 1, 1, 0, 0, 0, 0);
        DT = DT.AddSeconds(timeStamp);
        return DT;
}
Run Code Online (Sandbox Code Playgroud)

使用时传输数据

(SomeStruct)Marshal.PtrToStructure(
 IntPtr,
 typeof(SomeStruct));
Run Code Online (Sandbox Code Playgroud)

我希望长时间使用上面的代码sinppet自动转换unix.我是否必须继承MarshalAs类并将转换写入此类?谢谢,Juergen

更新 这里是自定义编组:

class MarshalTest : ICustomMarshaler
{
    public void CleanUpManagedData(object ManagedObj)
    {
        throw new NotImplementedException();
    }

    public void CleanUpNativeData(IntPtr pNativeData)
    {
        throw new NotImplementedException();
    }

    public int GetNativeDataSize()
    {
        return 8;
    }

    public IntPtr MarshalManagedToNative(object ManagedObj)
    {
        throw new NotImplementedException();
    }

    public object MarshalNativeToManaged(IntPtr pNativeData)
    {
        long UnixTime = 0;
        try
        {
            UnixTime = Marshal.ReadInt64(pNativeData);
        }
        catch (Exception e)
        {

           QFXLogger.Error(e, "MarshalNativeToManaged");
        }
        DateTime DT = new DateTime(1970, 1, 1, 0, 0, 0, 0);
        DT = DT.AddSeconds(UnixTime);
        return DT;
    }
 }
Run Code Online (Sandbox Code Playgroud)

这是类定义:

unsafe public struct MT5ServerAttributes
{
    /// <summary>
    /// Last known server time.
    /// </summary>
    [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(MarshalTest))]
    public DateTime CurrentTime;

    //[MarshalAs(UnmanagedType.U8)]
    [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(MarshalTest))]
    public DateTime TradeTime;

 }
Run Code Online (Sandbox Code Playgroud)

最后是编组来自非托管内存的数据的代码:

try
{
   MT5ServerAttributes MT5SrvAttributes = (MT5ServerAttributes)Marshal.PtrToStructure(mMT5Proxy.MT5InformationProxy.ServerData,
                                                                    typeof(MT5ServerAttributes));
}
catch (Exception e)
{

QFXLogger.Error(e, "ConsumeCommand inner");
}
Run Code Online (Sandbox Code Playgroud)

运行此时,将抛出以下excpetion(这不是PtrToStructure的直接例外!)无法编组'QFX_DLL.MT5ServerAttributes'类型的字段'CurrentTime':无效的托管/非托管类型组合(DateTime类必须与Struct配对).有任何想法吗?

vcs*_*nes 5

您无法将自己的内容添加到枚举中,但可以使用UnmanagedType.CustomMarshaler.指定要使用自定义类型封送它.

MSDN有一整个专门用于此的部分.

你最终会沿着这些方向做一些事情:

[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(MyCustomMarshaler))]
public DateTime Time;
Run Code Online (Sandbox Code Playgroud)

然后实现MyCustomMarshaler as ICustomMarshaler.

  • 不,@JN对我来说都不高兴.我怀疑他的评论是@Juergen在实际尝试之前将其标记为答案.如果跳过调用`Marshal.SizeOf`和直接去`Marshal.PtrToStructure`呼叫的步骤,你会得到**错误"自定义封送拆无法对结构的领域."**这几乎说它无法完成. (4认同)