2013-03-22 15 views
2

如果我有這樣的事情:我會如何發出歧視的工會?

type public ServiceActionType = 
    | ServiceRequest 
    | ServiceResponse 
    | ServiceEventInvocation 
    | ServiceEventSubscriptionRequest 
    | ServiceMetadataRequest 

我怎麼再加入這些項目中的一個堆棧,如:

IlGen.Emit(OpCodes.???, ???) 

回答

4

總的來說,歧視工會編譯成類層次結構(這意味着每個受歧視工會的案例都有一個新的子類)。但是,就你而言,情況更簡單,因爲沒有任何情況具有任何價值。

如果你看一下編譯後的代碼,你會看到生成.NET代表給你的東西,如:

class ServiceActionType { 
    public static ServiceActionType ServiceRequest { get; } 
    public static ServiceActionType ServiceResponse { get; } 
    public static ServiceActionType ServiceEventInvocation { get; } 
    // etc. for all the other cases 
} 

這意味着,如果你想構建歧視的價值觀之一聯合,你只需要發出一個調用代表你想要的情況的(靜態)屬性的getter方法。

如果您有相關的參數的情況下,說ServiceRequest of RequestInfo,然後將生成的類將包括NewServiceRequest方法來代替,這將採取必要的參數:

public static ServiceActionType NewServiceRequest(RequestInfo info); 

這就是說,我不完全知道爲什麼你想這樣做,所以發射代碼可能不是最好的方法。您還可以考慮使用F#語句 - 可以將其編譯爲動態方法 - 並使用Expr.NewUnionCase創建代表DU結構的引用非常簡單。

+0

完美,有道理 – sircodesalot 2013-03-22 15:26:57

+0

'我不完全確定你爲什麼要這樣做,試圖將用戶定義的接口包裝在具體的類中(用於服務類型調用)。除非有更好的方法來做到這一點? – sircodesalot 2013-03-22 16:50:10

+0

@sircodesalot不知道我完全理解 - 你是否試圖自動構建圍繞F#歧義工會的包裝以匹配調用者提供的某些類/接口類型? (這聽起來很有趣......) – 2013-03-22 19:42:21

2

舉個例子,我們以ServiceActionType.ServiceRequest爲例。

我把下面的LINQPad(F#編程模式),以獲得IL(但是你可以使用ildasm.exe爲了同樣的目的):

type public ServiceActionType = 
    | ServiceRequest 
    | ServiceResponse 
    | ServiceEventInvocation 
    | ServiceEventSubscriptionRequest 
    | ServiceMetadataRequest 

ServiceRequest.Dump() 

,它給了我:

IL_0001: call  Query_qdoovg+ServiceActionType.get_ServiceRequest 
IL_0006: call  LINQPad.FSharpExtensions.Extensions.Dump 

Dump: 
IL_0000: nop   
IL_0001: ldarg.0  
IL_0002: box   03 00 00 1B 
IL_0007: call  LINQPad.FSharpExtensions.Extensions.Dump 
IL_000C: ret   

ServiceActionType.get_ServiceMetadataRequest: 
IL_0000: ldsfld  Query_qdoovg+ServiceActionType._unique_ServiceMetadataRequest 
IL_0005: ret   

ServiceActionType.get_IsServiceMetadataRequest: 
IL_0000: ldarg.0  
IL_0001: call  Query_qdoovg+ServiceActionType.get_Tag 
IL_0006: ldc.i4.4  
IL_0007: ceq   
IL_0009: ret   

ServiceActionType.get_ServiceEventSubscriptionRequest: 
IL_0000: ldsfld  Query_qdoovg+ServiceActionType._unique_ServiceEventSubscriptionRequest 
IL_0005: ret   

ServiceActionType.get_IsServiceEventSubscriptionRequest: 
IL_0000: ldarg.0  
IL_0001: call  Query_qdoovg+ServiceActionType.get_Tag 
IL_0006: ldc.i4.3  
IL_0007: ceq   
IL_0009: ret   

ServiceActionType.get_ServiceEventInvocation: 
IL_0000: ldsfld  Query_qdoovg+ServiceActionType._unique_ServiceEventInvocation 
IL_0005: ret   

ServiceActionType.get_IsServiceEventInvocation: 
IL_0000: ldarg.0  
IL_0001: call  Query_qdoovg+ServiceActionType.get_Tag 
IL_0006: ldc.i4.2  
IL_0007: ceq   
IL_0009: ret   

ServiceActionType.get_ServiceResponse: 
IL_0000: ldsfld  Query_qdoovg+ServiceActionType._unique_ServiceResponse 
IL_0005: ret   

ServiceActionType.get_IsServiceResponse: 
IL_0000: ldarg.0  
IL_0001: call  Query_qdoovg+ServiceActionType.get_Tag 
IL_0006: ldc.i4.1  
IL_0007: ceq   
IL_0009: ret   

ServiceActionType.get_ServiceRequest: 
IL_0000: ldsfld  Query_qdoovg+ServiceActionType._unique_ServiceRequest 
IL_0005: ret   

ServiceActionType.get_IsServiceRequest: 
IL_0000: ldarg.0  
IL_0001: call  Query_qdoovg+ServiceActionType.get_Tag 
IL_0006: ldc.i4.0  
IL_0007: ceq   
IL_0009: ret   

ServiceActionType.get_Tag: 
IL_0000: ldarg.0  
IL_0001: ldfld  Query_qdoovg+ServiceActionType._tag 
IL_0006: ret   

ServiceActionType.__DebugDisplay: 
IL_0000: ldstr  "%+0.8A" 
IL_0005: newobj  Microsoft.FSharp.Core.PrintfFormat<Microsoft.FSharp.Core.FSharpFunc<Query_qdoovg+ServiceActionType,System.String>,Microsoft.FSharp.Core.Unit,System.String,System.String,System.String>..ctor 
IL_000A: call  Microsoft.FSharp.Core.ExtraTopLevelOperators.PrintFormatToString 
IL_000F: ldarg.0  
IL_0010: callvirt Microsoft.FSharp.Core.FSharpFunc<Query_qdoovg+ServiceActionType,System.String>.Invoke 
IL_0015: ret   

ServiceActionType.CompareTo: 
IL_0000: nop   
IL_0001: ldarg.0  
IL_0002: ldnull  
IL_0003: cgt.un  
IL_0005: brfalse.s IL_0027 
IL_0007: ldarg.1  
IL_0008: ldnull  
IL_0009: cgt.un  
IL_000B: brfalse.s IL_0025 
IL_000D: ldarg.0  
IL_000E: ldfld  Query_qdoovg+ServiceActionType._tag 
IL_0013: stloc.0  
IL_0014: ldarg.1  
IL_0015: ldfld  Query_qdoovg+ServiceActionType._tag 
IL_001A: stloc.1  
IL_001B: ldloc.0  
IL_001C: ldloc.1  
IL_001D: bne.un.s IL_0021 
IL_001F: ldc.i4.0  
IL_0020: ret   
IL_0021: ldloc.0  
IL_0022: ldloc.1  
IL_0023: sub   
IL_0024: ret   
IL_0025: ldc.i4.1  
IL_0026: ret   
IL_0027: ldarg.1  
IL_0028: ldnull  
IL_0029: cgt.un  
IL_002B: brfalse.s IL_002F 
IL_002D: ldc.i4.m1 
IL_002E: ret   
IL_002F: ldc.i4.0  
IL_0030: ret   

ServiceActionType.CompareTo: 
IL_0000: nop   
IL_0001: ldarg.0  
IL_0002: ldarg.1  
IL_0003: unbox.any Query_qdoovg.ServiceActionType 
IL_0008: call  Query_qdoovg+ServiceActionType.CompareTo 
IL_000D: ret   

ServiceActionType.CompareTo: 
IL_0000: nop   
IL_0001: ldarg.1  
IL_0002: unbox.any Query_qdoovg.ServiceActionType 
IL_0007: stloc.0  
IL_0008: ldarg.0  
IL_0009: ldnull  
IL_000A: cgt.un  
IL_000C: brfalse.s IL_0033 
IL_000E: ldarg.1  
IL_000F: unbox.any Query_qdoovg.ServiceActionType 
IL_0014: ldnull  
IL_0015: cgt.un  
IL_0017: brfalse.s IL_0031 
IL_0019: ldarg.0  
IL_001A: ldfld  Query_qdoovg+ServiceActionType._tag 
IL_001F: stloc.1  
IL_0020: ldloc.0  
IL_0021: ldfld  Query_qdoovg+ServiceActionType._tag 
IL_0026: stloc.2  
IL_0027: ldloc.1  
IL_0028: ldloc.2  
IL_0029: bne.un.s IL_002D 
IL_002B: ldc.i4.0  
IL_002C: ret   
IL_002D: ldloc.1  
IL_002E: ldloc.2  
IL_002F: sub   
IL_0030: ret   
IL_0031: ldc.i4.1  
IL_0032: ret   
IL_0033: ldarg.1  
IL_0034: unbox.any Query_qdoovg.ServiceActionType 
IL_0039: ldnull  
IL_003A: cgt.un  
IL_003C: brfalse.s IL_0040 
IL_003E: ldc.i4.m1 
IL_003F: ret   
IL_0040: ldc.i4.0  
IL_0041: ret   

ServiceActionType.GetHashCode: 
IL_0000: nop   
IL_0001: ldarg.0  
IL_0002: ldnull  
IL_0003: cgt.un  
IL_0005: brfalse.s IL_003C 
IL_0007: ldc.i4.0  
IL_0008: stloc.0  
IL_0009: ldarg.0  
IL_000A: call  Query_qdoovg+ServiceActionType.get_Tag 
IL_000F: switch  (IL_0028, IL_002C, IL_0030, IL_0034, IL_0038) 
IL_0028: ldc.i4.0  
IL_0029: stloc.0  
IL_002A: ldloc.0  
IL_002B: ret   
IL_002C: ldc.i4.1  
IL_002D: stloc.0  
IL_002E: ldloc.0  
IL_002F: ret   
IL_0030: ldc.i4.2  
IL_0031: stloc.0  
IL_0032: ldloc.0  
IL_0033: ret   
IL_0034: ldc.i4.3  
IL_0035: stloc.0  
IL_0036: ldloc.0  
IL_0037: ret   
IL_0038: ldc.i4.4  
IL_0039: stloc.0  
IL_003A: ldloc.0  
IL_003B: ret   
IL_003C: ldc.i4.0  
IL_003D: ret   

ServiceActionType.GetHashCode: 
IL_0000: nop   
IL_0001: ldarg.0  
IL_0002: call  Microsoft.FSharp.Core.LanguagePrimitives.get_GenericEqualityComparer 
IL_0007: call  Query_qdoovg+ServiceActionType.GetHashCode 
IL_000C: ret   

ServiceActionType.Equals: 
IL_0000: nop   
IL_0001: ldarg.0  
IL_0002: ldnull  
IL_0003: cgt.un  
IL_0005: brfalse.s IL_0026 
IL_0007: ldarg.1  
IL_0008: isinst  Query_qdoovg.ServiceActionType 
IL_000D: stloc.0  
IL_000E: ldloc.0  
IL_000F: brfalse.s IL_0024 
IL_0011: ldarg.0  
IL_0012: ldfld  Query_qdoovg+ServiceActionType._tag 
IL_0017: stloc.1  
IL_0018: ldloc.0  
IL_0019: ldfld  Query_qdoovg+ServiceActionType._tag 
IL_001E: stloc.2  
IL_001F: ldloc.1  
IL_0020: ldloc.2  
IL_0021: ceq   
IL_0023: ret   
IL_0024: ldc.i4.0  
IL_0025: ret   
IL_0026: ldarg.1  
IL_0027: ldnull  
IL_0028: cgt.un  
IL_002A: ldc.i4.0  
IL_002B: ceq   
IL_002D: ret   

ServiceActionType.Equals: 
IL_0000: nop   
IL_0001: ldarg.0  
IL_0002: ldnull  
IL_0003: cgt.un  
IL_0005: brfalse.s IL_0022 
IL_0007: ldarg.1  
IL_0008: ldnull  
IL_0009: cgt.un  
IL_000B: brfalse.s IL_0020 
IL_000D: ldarg.0  
IL_000E: ldfld  Query_qdoovg+ServiceActionType._tag 
IL_0013: stloc.0  
IL_0014: ldarg.1  
IL_0015: ldfld  Query_qdoovg+ServiceActionType._tag 
IL_001A: stloc.1  
IL_001B: ldloc.0  
IL_001C: ldloc.1  
IL_001D: ceq   
IL_001F: ret   
IL_0020: ldc.i4.0  
IL_0021: ret   
IL_0022: ldarg.1  
IL_0023: ldnull  
IL_0024: cgt.un  
IL_0026: ldc.i4.0  
IL_0027: ceq   
IL_0029: ret   

ServiceActionType.Equals: 
IL_0000: nop   
IL_0001: ldarg.1  
IL_0002: isinst  Query_qdoovg.ServiceActionType 
IL_0007: stloc.0  
IL_0008: ldloc.0  
IL_0009: brfalse.s IL_0013 
IL_000B: ldarg.0  
IL_000C: ldloc.0  
IL_000D: call  Query_qdoovg+ServiceActionType.Equals 
IL_0012: ret   
IL_0013: ldc.i4.0  
IL_0014: ret   

ServiceActionType..ctor: 
IL_0000: ldarg.0  
IL_0001: call  System.Object..ctor 
IL_0006: ldarg.0  
IL_0007: ldarg.1  
IL_0008: stfld  Query_qdoovg+ServiceActionType._tag 
IL_000D: ret   

IL_0001: call Query_qdoovg+ServiceActionType.get_ServiceRequest是執行call指令來獲取堆棧上的ServiceActionType.ServiceRequest值的位。

這可能是發出這樣的:il.Emit(OpCodes.Call, typeof<ServiceActionType>.GetMethod("get_ServiceRequest"))

6

現有的回答都不錯,但要注意,Microsoft.FSharp.Reflection命名空間有一些助手,可以輕鬆獲得您所關心的成員:

open Reflection 
let cases = FSharpType.GetUnionCases(typeof<ServiceActionType>) 
let serviceRequestMethod = FSharpValue.PreComputeUnionConstructorInfo(cases.[0]) 

結果與typeof<ServiceActionType>.GetMethod("get_ServiceRequest")的結果相同,但您不必擔心知道編譯後的表單,該表單可以根據工會案例是否具有字段而有所不同。

+0

+1好點。這當然是獲取方法信息對象的更好方法! – 2013-03-22 19:41:04