提交 7bc69c42 编写于 作者: D dsyme

add WPF path to fsi.exe and cleanup resolution flags

上级 86fcbe34
...@@ -2213,7 +2213,7 @@ type TcConfigBuilder = ...@@ -2213,7 +2213,7 @@ type TcConfigBuilder =
useFsiAuxLib=false useFsiAuxLib=false
implicitOpens=[] implicitOpens=[]
includes=[] includes=[]
resolutionEnvironment=ReferenceResolver.CompileTimeLike resolutionEnvironment=ResolutionEnvironment.EditingAndCompilation false
framework=true framework=true
implicitlyResolveAssemblies=true implicitlyResolveAssemblies=true
referencedDLLs = [] referencedDLLs = []
...@@ -2801,46 +2801,52 @@ type TcConfig private (data : TcConfigBuilder,validate:bool) = ...@@ -2801,46 +2801,52 @@ type TcConfig private (data : TcConfigBuilder,validate:bool) =
// This call can fail if no CLR is found (this is the path to mscorlib) // This call can fail if no CLR is found (this is the path to mscorlib)
member tcConfig.GetTargetFrameworkDirectories() = member tcConfig.GetTargetFrameworkDirectories() =
use unwindBuildPhase = PushThreadBuildPhaseUntilUnwind BuildPhase.Parameter use unwindBuildPhase = PushThreadBuildPhaseUntilUnwind BuildPhase.Parameter
match tcConfig.clrRoot with try
| Some x -> [
[tcConfig.MakePathAbsolute x] // Check if we are given an explicit framework root - if so, use that
| None -> match tcConfig.clrRoot with
#if ENABLE_MONO_SUPPORT | Some x ->
if runningOnMono then yield tcConfig.MakePathAbsolute x
[ let runtimeRoot = System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory()
let runtimeRootWithoutSlash = runtimeRoot.TrimEnd('/', '\\') | None ->
let api = runtimeRootWithoutSlash + "-api" let runtimeRoot = System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory()
let rootFacades = Path.Combine(runtimeRootWithoutSlash, "Facades") let runtimeRootWithoutSlash = runtimeRoot.TrimEnd('/', '\\')
let apiFacades = Path.Combine(api, "Facades") let runtimeRootFacades = Path.Combine(runtimeRootWithoutSlash, "Facades")
match tcConfig.resolutionEnvironment with let runtimeRootWPF = Path.Combine(runtimeRootWithoutSlash, "WPF")
#if !FSI_TODO_NETCORE
// For F# Interactive code we must inly reference impementation assemblies match tcConfig.resolutionEnvironment with
| ReferenceResolver.RuntimeLike -> | ResolutionEnvironment.CompilationAndEvaluation ->
yield runtimeRoot // Default compilation-and-execution-time references on .NET Framework and Mono, e.g. for F# Interactive
if Directory.Exists(rootFacades) then //
yield rootFacades // System.Runtime.dll is in /usr/lib/mono/4.5/Facades // In the current way of doing things, F# Interactive refers to implementation assemblies.
#endif yield runtimeRoot
| _ -> if Directory.Exists(runtimeRootFacades) then
// The default FSharp.Core is found in lib/mono/4.5 yield runtimeRootFacades // System.Runtime.dll is in /usr/lib/mono/4.5/Facades
yield runtimeRoot if Directory.Exists(runtimeRootWPF) then
if Directory.Exists(rootFacades) then yield runtimeRootWPF // PresentationCore.dll is in C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF
yield rootFacades // System.Runtime.dll is in /usr/lib/mono/4.5/Facades
// It's not clear why we would need to reference the 4.5-api directory. | ResolutionEnvironment.EditingAndCompilation _ ->
if Directory.Exists(api) then if runningOnMono then
yield api // Default compilation-time references on Mono
if Directory.Exists(apiFacades) then //
yield apiFacades // On Mono, the default references come from the implementation assemblies.
] // This is because we have had trouble reliably using MSBuild APIs to compute DotNetFrameworkReferenceAssembliesRootDirectory on Mono.
else yield runtimeRoot
#endif if Directory.Exists(runtimeRootFacades) then
try yield runtimeRootFacades // System.Runtime.dll is in /usr/lib/mono/4.5/Facades
[ if Directory.Exists(runtimeRootWPF) then
match tcConfig.resolutionEnvironment with yield runtimeRootWPF // PresentationCore.dll is in C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF
#if !FSI_TODO_NETCORE // On Mono we also add a default reference to the 4.5-api and 4.5-api/Facades directories.
| ReferenceResolver.RuntimeLike -> let runtimeRootApi = runtimeRootWithoutSlash + "-api"
yield System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory() let runtimeRootApiFacades = Path.Combine(runtimeRootApi, "Facades")
#endif if Directory.Exists(runtimeRootApi) then
| _ -> yield runtimeRootApi
if Directory.Exists(runtimeRootApiFacades) then
yield runtimeRootApiFacades
else
// Default compilation-time references on .NET Framework
//
// This is the normal case for "fsc.exe a.fs". We refer to the reference assemblies folder.
let frameworkRoot = tcConfig.legacyReferenceResolver.DotNetFrameworkReferenceAssembliesRootDirectory let frameworkRoot = tcConfig.legacyReferenceResolver.DotNetFrameworkReferenceAssembliesRootDirectory
let frameworkRootVersion = Path.Combine(frameworkRoot,tcConfig.targetFrameworkVersion) let frameworkRootVersion = Path.Combine(frameworkRoot,tcConfig.targetFrameworkVersion)
yield frameworkRootVersion yield frameworkRootVersion
...@@ -2848,8 +2854,8 @@ type TcConfig private (data : TcConfigBuilder,validate:bool) = ...@@ -2848,8 +2854,8 @@ type TcConfig private (data : TcConfigBuilder,validate:bool) =
if Directory.Exists(facades) then if Directory.Exists(facades) then
yield facades yield facades
] ]
with e -> with e ->
errorRecovery e range0; [] errorRecovery e range0; []
member tcConfig.ComputeLightSyntaxInitialStatus(filename) = member tcConfig.ComputeLightSyntaxInitialStatus(filename) =
use unwindBuildPhase = PushThreadBuildPhaseUntilUnwind BuildPhase.Parameter use unwindBuildPhase = PushThreadBuildPhaseUntilUnwind BuildPhase.Parameter
...@@ -4854,7 +4860,7 @@ type LoadClosure = ...@@ -4854,7 +4860,7 @@ type LoadClosure =
[<RequireQualifiedAccess>] [<RequireQualifiedAccess>]
type CodeContext = type CodeContext =
| Evaluation // in fsi.exe | CompilationAndEvaluation // in fsi.exe
| Compilation // in fsc.exe | Compilation // in fsc.exe
| Editing // in VS | Editing // in VS
...@@ -4887,7 +4893,7 @@ module private ScriptPreprocessClosure = ...@@ -4887,7 +4893,7 @@ module private ScriptPreprocessClosure =
// .fsx -- EDITING + !COMPILED\INTERACTIVE // .fsx -- EDITING + !COMPILED\INTERACTIVE
let defines = let defines =
match codeContext with match codeContext with
| CodeContext.Evaluation -> ["INTERACTIVE"] | CodeContext.CompilationAndEvaluation -> ["INTERACTIVE"]
| CodeContext.Compilation -> ["COMPILED"] | CodeContext.Compilation -> ["COMPILED"]
| CodeContext.Editing -> "EDITING" :: (if IsScript filename then ["INTERACTIVE"] else ["COMPILED"]) | CodeContext.Editing -> "EDITING" :: (if IsScript filename then ["INTERACTIVE"] else ["COMPILED"])
let lexbuf = UnicodeLexing.StringAsLexbuf source let lexbuf = UnicodeLexing.StringAsLexbuf source
...@@ -4898,7 +4904,7 @@ module private ScriptPreprocessClosure = ...@@ -4898,7 +4904,7 @@ module private ScriptPreprocessClosure =
/// Create a TcConfig for load closure starting from a single .fsx file /// Create a TcConfig for load closure starting from a single .fsx file
let CreateScriptSourceTcConfig (legacyReferenceResolver, defaultFSharpBinariesDir, filename:string, codeContext, useSimpleResolution, useFsiAuxLib, basicReferences, applyCommandLineArgs, assumeDotNetFramework) = let CreateScriptSourceTcConfig (legacyReferenceResolver, defaultFSharpBinariesDir, filename:string, codeContext, useSimpleResolution, useFsiAuxLib, basicReferences, applyCommandLineArgs, assumeDotNetFramework) =
let projectDir = Path.GetDirectoryName(filename) let projectDir = Path.GetDirectoryName(filename)
let isInteractive = (codeContext = CodeContext.Evaluation) let isInteractive = (codeContext = CodeContext.CompilationAndEvaluation)
let isInvalidationSupported = (codeContext = CodeContext.Editing) let isInvalidationSupported = (codeContext = CodeContext.Editing)
let tcConfigB = TcConfigBuilder.CreateNew(legacyReferenceResolver, defaultFSharpBinariesDir, true (* optimize for memory *), projectDir, isInteractive, isInvalidationSupported, defaultCopyFSharpCore=false) let tcConfigB = TcConfigBuilder.CreateNew(legacyReferenceResolver, defaultFSharpBinariesDir, true (* optimize for memory *), projectDir, isInteractive, isInvalidationSupported, defaultCopyFSharpCore=false)
applyCommandLineArgs tcConfigB applyCommandLineArgs tcConfigB
...@@ -4908,12 +4914,14 @@ module private ScriptPreprocessClosure = ...@@ -4908,12 +4914,14 @@ module private ScriptPreprocessClosure =
tcConfigB.resolutionEnvironment <- tcConfigB.resolutionEnvironment <-
match codeContext with match codeContext with
| CodeContext.Editing -> ReferenceResolver.DesignTimeLike | CodeContext.Editing -> ResolutionEnvironment.EditingAndCompilation true
| CodeContext.Compilation -> ResolutionEnvironment.EditingAndCompilation false
| CodeContext.CompilationAndEvaluation ->
#if FSI_TODO_NETCORE #if FSI_TODO_NETCORE
// "RuntimeLike" assembly resolution for F# Interactive is not yet properly figured out on .NET Core // "CompilationAndEvaluation" assembly resolution for F# Interactive is not yet properly figured out on .NET Core
| CodeContext.Compilation | CodeContext.Evaluation -> ReferenceResolver.CompileTimeLike ResolutionEnvironment.EditingAndCompilation false
#else #else
| CodeContext.Compilation | CodeContext.Evaluation -> ReferenceResolver.RuntimeLike ResolutionEnvironment.CompilationAndEvaluation
#endif #endif
tcConfigB.framework <- false tcConfigB.framework <- false
tcConfigB.useSimpleResolution <- useSimpleResolution tcConfigB.useSimpleResolution <- useSimpleResolution
......
...@@ -761,7 +761,7 @@ val ReportWarningAsError : globalWarnLevel: int * specificWarnOff: int list * sp ...@@ -761,7 +761,7 @@ val ReportWarningAsError : globalWarnLevel: int * specificWarnOff: int list * sp
[<RequireQualifiedAccess>] [<RequireQualifiedAccess>]
type CodeContext = type CodeContext =
| Evaluation | CompilationAndEvaluation
| Compilation | Compilation
| Editing | Editing
......
...@@ -287,11 +287,12 @@ module internal Microsoft.FSharp.Compiler.MSBuildReferenceResolver ...@@ -287,11 +287,12 @@ module internal Microsoft.FSharp.Compiler.MSBuildReferenceResolver
let registry = sprintf "{Registry:%s,%s,%s%s}" frameworkRegistryBase targetFrameworkVersion assemblyFoldersSuffix assemblyFoldersConditions let registry = sprintf "{Registry:%s,%s,%s%s}" frameworkRegistryBase targetFrameworkVersion assemblyFoldersSuffix assemblyFoldersConditions
[| // When compiling scripts, for some reason we have always historically put TargetFrameworkDirectory first [| // When compiling scripts using fsc.exe, for some reason we have always historically put TargetFrameworkDirectory first
// It is unclear why. // It is unclear why. This is the only place we look at the 'isdifference between ResolutionEnvironment.EditingAndCompilation and ResolutionEnvironment.EditingTime.
match resolutionEnvironment with match resolutionEnvironment with
| CompileTimeLike -> yield "{TargetFrameworkDirectory}" | ResolutionEnvironment.EditingAndCompilation false -> yield "{TargetFrameworkDirectory}"
| DesignTimeLike | RuntimeLike -> () | ResolutionEnvironment.EditingAndCompilation true
| ResolutionEnvironment.CompilationAndEvaluation -> ()
// Quick-resolve straight to filename first // Quick-resolve straight to filename first
if allowRawFileName then if allowRawFileName then
...@@ -301,8 +302,9 @@ module internal Microsoft.FSharp.Compiler.MSBuildReferenceResolver ...@@ -301,8 +302,9 @@ module internal Microsoft.FSharp.Compiler.MSBuildReferenceResolver
yield implicitIncludeDir // Usually the project directory yield implicitIncludeDir // Usually the project directory
match resolutionEnvironment with match resolutionEnvironment with
| DesignTimeLike | RuntimeLike -> yield "{TargetFrameworkDirectory}" | ResolutionEnvironment.EditingAndCompilation true
| CompileTimeLike -> () | ResolutionEnvironment.CompilationAndEvaluation -> yield "{TargetFrameworkDirectory}"
| ResolutionEnvironment.EditingAndCompilation false -> ()
yield registry yield registry
yield "{AssemblyFolders}" yield "{AssemblyFolders}"
......
...@@ -10,13 +10,12 @@ module internal ReferenceResolver = ...@@ -10,13 +10,12 @@ module internal ReferenceResolver =
exception internal ResolutionFailure exception internal ResolutionFailure
[<RequireQualifiedAccess>]
type ResolutionEnvironment = type ResolutionEnvironment =
/// Indicates a script or source being compiled /// Indicates a script or source being compiled. Uses reference assemblies (not implementation assemblies).
| CompileTimeLike | EditingAndCompilation of isEditing: bool
/// Indicates a script or source being interpreted /// Indicates a script or source being dynamically compiled and executed. Uses implementation assemblies.
| RuntimeLike | CompilationAndEvaluation
/// Indicates a script or source being edited
| DesignTimeLike
type ResolvedFile = type ResolvedFile =
{ /// Item specification. { /// Item specification.
......
...@@ -208,7 +208,7 @@ let fscoreDir = ...@@ -208,7 +208,7 @@ let fscoreDir =
System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory() System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory()
let resolve s = let resolve s =
SimulatedMSBuildResolver.Resolve(ResolutionEnvironment.CompileTimeLike,[| for a in s -> (a, "") |],"v4.5.1", [SimulatedMSBuildResolver.DotNetFrameworkReferenceAssembliesRootDirectory + @"\v4.5.1" ],"", "", fscoreDir,[],__SOURCE_DIRECTORY__,ignore, (fun _ _ -> ()), (fun _ _-> ())) SimulatedMSBuildResolver.Resolve(ResolutionEnvironment.EditingAndCompilation,[| for a in s -> (a, "") |],"v4.5.1", [SimulatedMSBuildResolver.DotNetFrameworkReferenceAssembliesRootDirectory + @"\v4.5.1" ],"", "", fscoreDir,[],__SOURCE_DIRECTORY__,ignore, (fun _ _ -> ()), (fun _ _-> ()))
// Resolve partial name to something on search path // Resolve partial name to something on search path
resolve ["FSharp.Core" ] resolve ["FSharp.Core" ]
......
...@@ -1291,7 +1291,7 @@ type internal FsiDynamicCompiler ...@@ -1291,7 +1291,7 @@ type internal FsiDynamicCompiler
let sourceFiles = sourceFiles |> List.map (fun nm -> tcConfig.ResolveSourceFile(m, nm, tcConfig.implicitIncludeDir),m) let sourceFiles = sourceFiles |> List.map (fun nm -> tcConfig.ResolveSourceFile(m, nm, tcConfig.implicitIncludeDir),m)
// Close the #load graph on each file and gather the inputs from the scripts. // Close the #load graph on each file and gather the inputs from the scripts.
let closure = LoadClosure.ComputeClosureOfSourceFiles(ctok, TcConfig.Create(tcConfigB,validate=false), sourceFiles, CodeContext.Evaluation,lexResourceManager=lexResourceManager) let closure = LoadClosure.ComputeClosureOfSourceFiles(ctok, TcConfig.Create(tcConfigB,validate=false), sourceFiles, CodeContext.CompilationAndEvaluation, lexResourceManager=lexResourceManager)
// Intent "[Loading %s]\n" (String.concat "\n and " sourceFiles) // Intent "[Loading %s]\n" (String.concat "\n and " sourceFiles)
fsiConsoleOutput.uprintf "[%s " (FSIstrings.SR.fsiLoadingFilesPrefixText()) fsiConsoleOutput.uprintf "[%s " (FSIstrings.SR.fsiLoadingFilesPrefixText())
...@@ -2459,12 +2459,12 @@ type FsiEvaluationSession (fsi: FsiEvaluationSessionHostConfig, argv:string[], i ...@@ -2459,12 +2459,12 @@ type FsiEvaluationSession (fsi: FsiEvaluationSessionHostConfig, argv:string[], i
let tcConfigB = TcConfigBuilder.CreateNew(legacyReferenceResolver, defaultFSharpBinariesDir=defaultFSharpBinariesDir, optimizeForMemory=true, implicitIncludeDir=currentDirectory, isInteractive=true, isInvalidationSupported=false, defaultCopyFSharpCore=false) let tcConfigB = TcConfigBuilder.CreateNew(legacyReferenceResolver, defaultFSharpBinariesDir=defaultFSharpBinariesDir, optimizeForMemory=true, implicitIncludeDir=currentDirectory, isInteractive=true, isInvalidationSupported=false, defaultCopyFSharpCore=false)
let tcConfigP = TcConfigProvider.BasedOnMutableBuilder(tcConfigB) let tcConfigP = TcConfigProvider.BasedOnMutableBuilder(tcConfigB)
do tcConfigB.resolutionEnvironment <- ReferenceResolver.RuntimeLike // See Bug 3608 do tcConfigB.resolutionEnvironment <- ReferenceResolver.ResolutionEnvironment.CompilationAndEvaluation // See Bug 3608
do tcConfigB.useFsiAuxLib <- fsi.UseFsiAuxLib do tcConfigB.useFsiAuxLib <- fsi.UseFsiAuxLib
#if FSI_TODO_NETCORE #if FSI_TODO_NETCORE
// "RuntimeLike" assembly resolution for F# Interactive is not yet properly figured out on .NET Core // "CompilationAndEvaluation" assembly resolution for F# Interactive is not yet properly figured out on .NET Core
do tcConfigB.resolutionEnvironment <- ReferenceResolver.DesignTimeLike do tcConfigB.resolutionEnvironment <- ResolutionEnvironment.EditingAndCompilation false
do tcConfigB.useSimpleResolution <- true do tcConfigB.useSimpleResolution <- true
do SetTargetProfile tcConfigB "netcore" // always assume System.Runtime codegen do SetTargetProfile tcConfigB "netcore" // always assume System.Runtime codegen
//do SetTargetProfile tcConfigB "privatecorelib" // always assume System.Private.CoreLib codegen //do SetTargetProfile tcConfigB "privatecorelib" // always assume System.Private.CoreLib codegen
......
...@@ -1701,7 +1701,8 @@ type IncrementalBuilder(tcGlobals,frameworkTcImports, nonFrameworkAssemblyInputs ...@@ -1701,7 +1701,8 @@ type IncrementalBuilder(tcGlobals,frameworkTcImports, nonFrameworkAssemblyInputs
// The following uses more memory but means we don't take read-exclusions on the DLLs we reference // The following uses more memory but means we don't take read-exclusions on the DLLs we reference
// Could detect well-known assemblies--ie System.dll--and open them with read-locks // Could detect well-known assemblies--ie System.dll--and open them with read-locks
tcConfigB.openBinariesInMemory <- true tcConfigB.openBinariesInMemory <- true
tcConfigB.resolutionEnvironment <- (if useScriptResolutionRules then ReferenceResolver.DesignTimeLike else ReferenceResolver.CompileTimeLike)
tcConfigB.resolutionEnvironment <- (ReferenceResolver.ResolutionEnvironment.EditingAndCompilation true)
tcConfigB.conditionalCompilationDefines <- tcConfigB.conditionalCompilationDefines <-
let define = if useScriptResolutionRules then "INTERACTIVE" else "COMPILED" let define = if useScriptResolutionRules then "INTERACTIVE" else "COMPILED"
......
...@@ -160,7 +160,7 @@ ...@@ -160,7 +160,7 @@
[assembly: SuppressMessage("Microsoft.Design", "CA1051:DoNotDeclareVisibleInstanceFields", Scope = "member", Target = "Microsoft.VisualStudio.Package.ProjectOptions.#BugReportFileName", MessageId = "")] [assembly: SuppressMessage("Microsoft.Design", "CA1051:DoNotDeclareVisibleInstanceFields", Scope = "member", Target = "Microsoft.VisualStudio.Package.ProjectOptions.#BugReportFileName", MessageId = "")]
[assembly: SuppressMessage("Microsoft.Design", "CA1051:DoNotDeclareVisibleInstanceFields", Scope = "member", Target = "Microsoft.VisualStudio.Package.ProjectOptions.#CheckedArithmetic", MessageId = "")] [assembly: SuppressMessage("Microsoft.Design", "CA1051:DoNotDeclareVisibleInstanceFields", Scope = "member", Target = "Microsoft.VisualStudio.Package.ProjectOptions.#CheckedArithmetic", MessageId = "")]
[assembly: SuppressMessage("Microsoft.Design", "CA1051:DoNotDeclareVisibleInstanceFields", Scope = "member", Target = "Microsoft.VisualStudio.Package.ProjectOptions.#CodePage", MessageId = "")] [assembly: SuppressMessage("Microsoft.Design", "CA1051:DoNotDeclareVisibleInstanceFields", Scope = "member", Target = "Microsoft.VisualStudio.Package.ProjectOptions.#CodePage", MessageId = "")]
[assembly: SuppressMessage("Microsoft.Design", "CA1051:DoNotDeclareVisibleInstanceFields", Scope = "member", Target = "Microsoft.VisualStudio.Package.ProjectOptions.#CompileAndExecute", MessageId = "")] [assembly: SuppressMessage("Microsoft.Design", "CA1051:DoNotDeclareVisibleInstanceFields", Scope = "member", Target = "Microsoft.VisualStudio.Package.ProjectOptions.#CompilationAndEvaluation", MessageId = "")]
[assembly: SuppressMessage("Microsoft.Design", "CA1051:DoNotDeclareVisibleInstanceFields", Scope = "member", Target = "Microsoft.VisualStudio.Package.ProjectOptions.#DefinedPreProcessorSymbols", MessageId = "")] [assembly: SuppressMessage("Microsoft.Design", "CA1051:DoNotDeclareVisibleInstanceFields", Scope = "member", Target = "Microsoft.VisualStudio.Package.ProjectOptions.#DefinedPreProcessorSymbols", MessageId = "")]
[assembly: SuppressMessage("Microsoft.Design", "CA1051:DoNotDeclareVisibleInstanceFields", Scope = "member", Target = "Microsoft.VisualStudio.Package.ProjectOptions.#DisplayCommandLineHelp", MessageId = "")] [assembly: SuppressMessage("Microsoft.Design", "CA1051:DoNotDeclareVisibleInstanceFields", Scope = "member", Target = "Microsoft.VisualStudio.Package.ProjectOptions.#DisplayCommandLineHelp", MessageId = "")]
[assembly: SuppressMessage("Microsoft.Design", "CA1051:DoNotDeclareVisibleInstanceFields", Scope = "member", Target = "Microsoft.VisualStudio.Package.ProjectOptions.#EmitManifest", MessageId = "")] [assembly: SuppressMessage("Microsoft.Design", "CA1051:DoNotDeclareVisibleInstanceFields", Scope = "member", Target = "Microsoft.VisualStudio.Package.ProjectOptions.#EmitManifest", MessageId = "")]
......
...@@ -71,7 +71,7 @@ public ProjectOptions(ConfigCanonicalName configCanonicalName) ...@@ -71,7 +71,7 @@ public ProjectOptions(ConfigCanonicalName configCanonicalName)
public string RootNamespace; public string RootNamespace;
public bool CompileAndExecute; public bool CompilationAndEvaluation;
/// <devdoc>must be an int if not null.</devdoc> /// <devdoc>must be an int if not null.</devdoc>
public object UserLocaleId; public object UserLocaleId;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册