A: A module is a collection of classes that do not have a manifest. This organizational level is used for several reasons:
1. Support generation of a single assembly from several different languages
2. Reduce download footprint for web applications. The CLR downloads only the main module by default; other modules are downloaded as needed.
3. Share small bits of common code that developers don't want to package into a separate assembly.
For more information, see this link.
A: .NET does not ship with any tool that does this, but it can be accomplished with PowerShell. To do so:
1. Create a file named "powershell.exe.config" in the project directory with the following content:
<?xml version="1.0"?>
<configuration>
<startup useLegacyV2RuntimeActivationPolicy="true">
<supportedRuntime version="v4.0.30319"/>
<supportedRuntime version="v2.0.50727"/>
</startup>
</configuration>
2. Create a file named "RunStub.ps1" in the project directory with the following contents:
#requires -version 2.0
# By David Luxford, 2014 August 4
# Validate command line parameters
if ($args.Length -eq 4)
{
$assemblyfilename = $args[0]
$namespace = $args[1]
$classname = $args[2]
$methodname = $args[3]
}
else
{
write-output "Method invoker"
write-output "Invokes a public static void( void ) method in a .NET assembly."
write-output ""
$noArgs = $args.Length
write-output "Insufficient command line parameters $noArgs, expected 4. Syntax:"
write-output "<assemblyFilename> <namespace> <className> <methodName>"
exit
}
# Initialize
write-output "Invoking $namespace.$classname.$methodname in $assemblyfilename"
#Load the assembly, class, and invoke the type
$targetAssembly = [Reflection.Assembly]::LoadFile($assemblyfilename)
$targetType = $targetAssembly.GetType("$namespace.$classname")
$targetType.InvokeMember("$methodname", 'Public,Static,InvokeMethod,DeclaredOnly', $null, $null, $null)2. In the class library project in Visual Studio, goto Project Properties.
3. Select the Debug tab.
4. Set Start Action to "Start external program", and set the text box to the following
<full pathname to bin directory>\powershell.exe
5. Set Command line arguments to the following, replacing <namespace>, <className>, and <methodName> with the actual values. Note assemblyFileFullPathname must be the full pathname to the assembly file in the debug bin directory:
-ExecutionPolicy ByPass -File "..\..\DebugStub.ps1" "<assemblyFileFullPathname>" <namespace> <className> <methodName>
6. Select the Build Events tab.
7. Set the Post build event command line to the following:
if not exist "$(TargetDir)\powershell.exe" copy "c:\windows\system32\WindowsPowerShell\v1.0\powershell.exe" $(TargetDir)
if not exist "$(TargetDir)\powershell.exe.config" copy "$(ProjectDir)\powershell.exe.config" $(TargetDir)
Notes:
Due to Visual Studio 2012 and below limitations, the paths on the Debug tab are machine specific. If using 2013, limited macros can be used here instead.
If symbol server supported is enabled, the first invocation may appear to hang as Visual Studio downloads the symbols for the .NET framework used by powershell.exe.
The source for the manifest trick is this link.
A: There are several possible causes. Before debugging, goto Project Properties|Debug and set Enable native code debugging. Rebuild the assembly, post the update, then try to debug again. After doing so, if the problem recurs, stop debugging and repost the DLL/PDB. Source is one of the responses to this question. Note that simply enabling the Native code debugger in the Attach to Process window will NOT fix this.
A: There are two ways to do this:
Use Reflection to call the private method InternalPreserveStackTrace on the exception object before throwing it, as in:
private static void PreserveStackTrace(Exception exception)
{
MethodInfo preserveStackTrace = typeof(Exception).GetMethod("InternalPreserveStackTrace",
BindingFlags.Instance | BindingFlags.NonPublic);
preserveStackTrace.Invoke(exception, null);
}
Courtesy this blog entry.
In NET 4.5 and above, recapture the original exception with System.Runtime.ExceptionServices.ExceptionDispatchInfo.Capture, then rethrow the resulting object in the new context using it's .Throw method. Courtesy this stack exchange posting. Note this is not quite identical to method #1 as the stack trace text includes a message "End of stack trace from the previous location where the exception was thrown".
A: Use the ILMerge tool. NOTE that specifying the correct set of reference assemblies is not obvious. For example, NET 4.5 was deployed as an "in-place" upgrade of 4.0, meaning that it replaces the 4.0 assemblies and otherwise is "fully compatible". However, the later is not true as some classes, such as the hidden ExtensionMethodAttribute class, have been moved to different assemblies. This can cause the ILMerge resultant assembly to fail if used incorrectly. To correct this, specify the authoritative set of reference assemblies for the NET framework version being targeted. These assemblies are installed to C:\Program Files\Reference Assemblies as of .NET 3.0 (2007) for precisely such a purpose. For example, if using ILMerge to create an assembly targetting .NET 4.0 on a machine with .NET 4.5 installed, you must use the following command line options:
/targetplatform:"v4,C:\Program Files\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0"
If instead you specify "c:\windows\Microsoft.NET\Framework\v4.0.30319", the resultant assembly will not work on .NET 4.0 because it will built to resolve .NET 4.0 classes in the new .NET 4.5 assemblies, but they are not there. However, the incorrect command line would work fine on a build machine with .NET 4.0 only. Courtesy this blog posting.
A: Use ildasm to decompile the built assembly, then ilasm to rebuild it and sign it. For more information, see this web page.
A: This is a WPF assembly. Either specify the path to the WPF assemblies via the /lib argument, or use /targetplatform only with a Reference Assemblies path. The following command line demonstrates the first solution, used on a machine with VS2013 which therefore lacks a NET 4.0 Reference Assemblies, so /targetplatform only is not an option
"C:\Program Files (x86)\Microsoft\ILMerge\ILMerge.exe" /ndebug /copyattrs /targetplatform:4,"C:\Windows\Microsoft.NET\Framework64\v4.0.30319" /lib:"C:\Windows\Microsoft.NET\Framework64\v4.0.30319\WPF" /out:"D:\duo_iis\InstallUtil\bin\x64\Debug\InstallUtilMerged.exe" "D:\duo_iis\InstallUtil\bin\x64\Debug\InstallUtil.exe" "D:\duo_iis\InstallUtil\bin\x64\Debug\DuoUtil.dll"
Courtesy this blog posting.
A: A certificate valid for use by a web server (HTTPS) has this usage embedded within the certificate data. In the .NET object model, this is reported in the X509Certificate2's Extensions collection under the Key Usage and Enhanced Key Usage extensions. In X509v2, an extension is a uniquely-identified blob of variable format data where the identifiers use OIDs, a string of period-separated integers such as 2.5.29.15. .NET includes parsers for both of these extensions and automatically parses them if found. To check the Key Usage and Enhanced Key Usage extensions, scan the Extensions collection for objects of type X509KeyUsageExtension and X509EnhancedKeyUsageExtension. To validate X509KeyUsageExtension, check the KeyUsages field. Validating X509EnhancedKeyUsageExtension is more difficult because this is a list of constants that NET does not appear to include. A list of the known usage identifiers can be found at this link, or by searching for information on the Enhanced Key Usage OID 2.5.29.37. The OIDs of the other commonly used extensions are Key Usage, 2.5.29.15, and Basic Constraints, 2.5.29.19. The later is parsed by X509BasicConstraintsExtension.
A: This is easy, but unobvious and undocumented. It requires use of the CertEnroll COM objects, which are present on Server 2012.
Add a reference to the COM type library "CertEnroll 1.0 Type Library", TLBID={728AB348-217D-11DA-B2A4-000E7BBB2B09}\1.0\0\tlbimp
Search the X509Certificate2's Extensions for the extension whose OID is 2.5.29.17
Get the RawData field from the SAN extension, the convert it to raw hex via BitConverter.ToString(rawData).Replace("-", "")
Create an CERTENROLLLib.CX509ExtensionAlternativeNames
Call InitializeDecode on the object created in step 3, passing it CERTENROLLLib.EncodingType.XCN_CRYPT_STRING_HEX and the raw hex string from step 3
Enumerate the AlternateNames collection of the CX509ExtensionAlternativeNames object as CERTENROLLLib.IAlternativeName
Ensure each name's type is CERTENROLLLib.AlternativeNameType.XCN_CERT_ALT_NAME_DNS_NAME
Source this article.
A: This is due to a reference to a missing definition for _TypePtr that is typically unneeded, and can be resolved by either removing the reference to it or providing the definition.
To remove generation of the reference to _TypePtr (recommended):
a. In the C# assembly generating the type library, decorate all ComVisible classes with [System.Runtime.InteropServices.ClassInterface(System.Runtime.InteropServices.ClassInterfaceType.None)].
To provide the reference for _TypePtr:
b. In the C++ client using the type library, add a #import for mscorlib.tlb above the #import for the C# assembly.
In either case, a Rebuild All is necessary to fix the build. Courtesy this stack overflow answer.
A: Use the barely documented COMFileReference MSBuild method. The easiest way to do so is:
Copy the file into the directory where it will live and register it if not registered.
Add a COM reference to that type library.
Save the project and build to ensure the build works.
Open the VCPROJ in a text editor.
Find the COMReference element and rename it to COMFileReference.
Change the Include attribute to be equal to the full pathname to the file created in step 1. You can use Visual Studio macros.
Delete all sub-elements of COMFileReference except for EmbedInteropTypes. COMFileReference supports TRUE and FALSE.
Save the file.
Manually clear the bin and obj directories to delete the interop DLLs generated by the last build.
Build the project.
Source is this stackoverflow answer.
A: They are in several locations, depending on the age of your Visual Studio version. The most authoritative version is C:\Program Files (x86)\Reference Assemblies. Despite the directory, the assemblies found here are the appropriate for either 32-bit or 64-bit builds. In older times, Microsoft stored the reference assemblies in C:\Program Files\Reference Assemblies. Copies of the NET 3.0 and 3.5 reference assemblies can still be found there.
A: It can't be done. This message is automatically generated by the framework initialization code and cannot be suppressed from a .NET host. To suppress it, you must write a C++ host and manually initialize the .NET framework. See this MSDN link
A: The valid parameter of this call requires that the cert be valid AND trusted. If it is not trusted, it will not be found. Change this parameter to FALSE.
A: This is due to a bug/unobvious requirement of FindByIdentity were it requires read rights to the Computers group in the forest, normally CN=Computers, in addition to the Users group in order to automatically determine the search context. To resolve this, specify the third argument when creating the PrincipalContext, the container. This should be the DC of the forest or domain where the user account exists, such as "DC=alpha, DC=local". Courtesy this MSDN blog posting.
A: The most likely cause is that one or more DllImports have been added to the class. C# does not allow DllImport declarations in Generic classes. To resolve this, move the DllImport members to a non-generic class.
A: This can only be done if .NET 4.5 or higher is installed. Also, if this is a Windows Server machine, it must be later than Server 2008 R0. To do so, manually set System.Net.ServicePointManager.SecurityProtocol to include the TLS 1.1 and 1.2 values. Because these constants are not available when targeting .NET 4.0, you must manually specify them. For example, use System.Enum.TryParse to parse the strings "Tls11" and "Tls12", then OR this onto the SecurityProtocol value. Note that if the FIRST request to the target host does not use TLS 1.2, then neither will subsequent requests - this is a separate issue in the .NET framework.
A: There is no proper API to do so programatically. To do so, you must use reflection to extract the log sources, connect them to a listener, and enable the System.Net debugging flag. To do so:
Create a System.Diagnostics.TextWriterTraceListener.
Get the System.Net.Logging type.
Get the static bool s_LoggingInitialized.
If !s_LoggingInitialized (normal in this case), get the static method InitializeLogging and invoke it.
Get the following static System.Diagnostics.TraceSource objects from the type:
s_WebTraceSource
s_HttpListenerTraceSource
s_SocketsTraceSource
s_CacheTraceSource
s_WebSocketsTraceSource
s_TraceSourceHttpName
For each of the above objects:
Set .Switch.Level to All (or the desired level).
Add your listener to the Listeners collection.
Get the static bool field s_LoggingEnabled from the type.
Set s_LoggingEnabled to TRUE.
A: Follow these instructions:
Run Microsoft's IL disassembler, installed as part of the Windows SDK in Microsoft SDKs\Windows\v7.0A\Bin\NETFX 4.0 Tools\x64\ildasm.exe.
Select File|Open, browse to the assembly, and click OK.
Select View|MetaInfo|Show
Scroll to the end of the listing and find the AssemblyRef block, just before the last major block titled User Strings.
All assembly references (dependent assemblies) are listed here in this format:
AssemblyRef #4 (23000004)
-------------------------------------------------------
Token: 0x23000004
Public Key or Token: b0 3f 5f 7f 11 d5 0a 3a
Name: System.Web
Version: 2.0.0.0
Major Version: 0x00000002
Minor Version: 0x00000000
Build Number: 0x00000000
Revision Number: 0x00000000
Locale: <null>
HashValue Blob:
Flags: [none] (00000000)
A: This is difficult. First, the framework version is not the same as the CLR, which is the underlying virtual machine executing the framework. In practice, however, since the two are always updated together, they are essentially the same. The problem is that the NET APIs report the CLR version, not the framework version, so it is difficult to differentiate between NET 4.0, 4.5, 4.5.1, etc. It turns out the best way to determine this for an app where you own the process is to get the version of clr.dll, then map the build number it to a table to determine the CLR version. The later part is only necessary for NET 4.0-4.5, as Microsoft stopped this with 4.6. The table is:
Courtesy this MSDN blog posting.
A: There are several ways. One of the easiest is to use WebServiceHost with System.ServiceModel.Web.WebInvoke. To do so:
1. Declare a standard WCF service class
2. Decorate each operation contract with WebInvoke, setting response and request formats to JSON and the appropriate Method.
3. For each operation contract, declare one DataContract class for all return values and one for all parameters.
4. Run Visual Studio as a local admin, or grant rights for non-elevated-admin use of the URL/port via netsh http add urlacl to the user/group that will run this.
In the example below, InstanceContextMode == Single is not required. This is done to permit control and configuration of the mock service for testing.
/// <summary>
/// Mockup of the Duo Auth service
/// </summary>
[System.ServiceModel.ServiceContract(SessionMode=System.ServiceModel.SessionMode.NotAllowed)]
[System.ServiceModel.ServiceBehavior(InstanceContextMode=System.ServiceModel.InstanceContextMode.Single, IncludeExceptionDetailInFaults=true)]
public class AuthServiceMock
{
[System.ServiceModel.OperationContract]
[System.ServiceModel.Web.WebInvoke(Method = "GET", ResponseFormat = System.ServiceModel.Web.WebMessageFormat.Json)]
public Duo.DuoResult<Duo.Authentication.ResultTime> ping()
{
var requestUri = System.ServiceModel.Web.WebOperationContext.Current.IncomingRequest.UriTemplateMatch.RequestUri;
Duo.DuoResult<Duo.Authentication.ResultTime> result = null;
result = new Duo.DuoResult<Duo.Authentication.ResultTime>();
result.methodResult = new Authentication.ResultTime();
result.methodResult.utcTime = DateTime.UtcNow;
result.methodSucceeded = "OK";
return result;
}
[DataContract]
public class ArgumentsGetCapabilities
{
[DataMember(Name="ipaddr", IsRequired=true)]
public string ipAddress;
[DataMember(Name="user_id")]
public string userID;
[DataMember(Name="username")]
public string userName;
[DataMember(Name="trusted_device_token")]
public string trustedDeviceToken;
}
[System.ServiceModel.OperationContract]
[System.ServiceModel.Web.WebInvoke(Method = "POST", ResponseFormat = System.ServiceModel.Web.WebMessageFormat.Json, RequestFormat=System.ServiceModel.Web.WebMessageFormat.Json)]
public Duo.DuoResult<Duo.Authentication.ResultAuthenticationCapabilities> preauth( ArgumentsGetCapabilities arguments )
{
var requestUri = System.ServiceModel.Web.WebOperationContext.Current.IncomingRequest.UriTemplateMatch.RequestUri;
var headers = System.ServiceModel.Web.WebOperationContext.Current.IncomingRequest.Headers;
var result = new Duo.DuoResult<Duo.Authentication.ResultAuthenticationCapabilities>();
result.methodResult = new Authentication.ResultAuthenticationCapabilities();
result.methodResult.statusMessage = "This is the status";
result.methodResult.mobileEnrollmentUrl = new Uri("http://www.nowhere.com");
result.methodSucceeded = "OK";
return result;
}
/// <summary>
/// Starts auth service mockup, reports endpoint to console and runs enter [enter] pressed
/// </summary>
public static void RunService()
{
Uri authServiceEndpoint = null;
AuthServiceMock actualService;
using (var host = CreateAndRunService(out authServiceEndpoint, out actualService))
{
Console.WriteLine("The service is ready at {0}", authServiceEndpoint);
Console.WriteLine("Press <Enter> to stop the service.");
Console.ReadLine();
host.Close();
}
}
/// <summary>
/// Creates an instance of the Duo Auth service mockup and returns it.
/// </summary>
/// <remarks>
/// Caller should dispose when done.
/// </remarks>
public static System.ServiceModel.Web.WebServiceHost CreateAndRunService( out Uri authEndpoint, out AuthServiceMock runningServiceInstance )
{
runningServiceInstance = new AuthServiceMock();
var host = new System.ServiceModel.Web.WebServiceHost(runningServiceInstance);
// Bind service contract to an Http REST GET/POST handler
// TODO: Use correct hostname for certificate
// TODO: Generate cert with appropriate hostname, trust cert, find free port, bind cert to port
var localHostname = "localhost";
var baseAddress = new Uri(String.Format("http://{0}:{1}/auth/v2", localHostname, 8085));
var webBinding = new System.ServiceModel.WebHttpBinding();
webBinding.Security.Transport.ClientCredentialType = System.ServiceModel.HttpClientCredentialType.None;
var serviceRestEndpoint = host.AddServiceEndpoint(typeof(AuthServiceMock), webBinding, baseAddress);
host.Open();
authEndpoint = baseAddress;
return host;
}
}
A: The current process has insufficient rights to receive on that URL. To resolve this, either run the process as an elevated local admin, or start an elevated command prompt and use netsh http add urlacl to grant rights to the user/group that will run this. Answer courtesy this stackoverflow post.
A: This is easy, but is the opposite of what is normally done. To do so:
Find the interface for the object and declare it with appropriate COM and marshaling attributes as usual.
Declare a class to represent the component, decorated with ComImport and Guid equal to the CLSID of the class.
Declare two variables, one for the class and one for the interface.
Instantiate the class type variable, then assign it to the interface type variable using a cast to assign it.
Call the methods as usual.
For example:
public static string GetProgIdForWebProtocol( string webprotocol )
{
var appRegistration = new ApplicationAssociationRegistration();
IApplicationAssociationRegistration appRegistrationActual = (IApplicationAssociationRegistration) appRegistration;
var assocationResult = appRegistrationActual.QueryCurrentDefault(webprotocol, ASSOCIATIONTYPE.AT_URLPROTOCOL, ASSOCIATIONLEVEL.AL_EFFECTIVE);
return assocationResult;
}
[ComImport]
[Guid("591209c7-767b-42b2-9fba-44ee4615f2c7")]
private class ApplicationAssociationRegistration
{
// Nothing needed - implementation provided by Runtime Callable Wrapper
}
[ComImport]
[Guid("4e530b0a-e611-4c77-a3ac-9031d022281b")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
private interface IApplicationAssociationRegistration
{
[return: MarshalAs(UnmanagedType.LPWStr)]
string QueryCurrentDefault( [MarshalAs(UnmanagedType.LPWStr)] string query, ASSOCIATIONTYPE queryType, ASSOCIATIONLEVEL queryLevel );
[return: MarshalAs(UnmanagedType.Bool)]
bool QueryAppIsDefault( [MarshalAs(UnmanagedType.LPWStr)] string query, ASSOCIATIONTYPE queryType, ASSOCIATIONLEVEL queryLevel, [MarshalAs(UnmanagedType.LPWStr)] string appRegistryName );
[return: MarshalAs(UnmanagedType.Bool)]
bool QueryAppIsDefaultAll( ASSOCIATIONLEVEL queryLevel, [MarshalAs(UnmanagedType.LPWStr)] string appRegistryName);
void SetAppAsDefault( [MarshalAs(UnmanagedType.LPWStr)] string appRegistryName, [MarshalAs(UnmanagedType.LPWStr)] string set, ASSOCIATIONTYPE setType );
void SetAppAsDefaultAll( [MarshalAs(UnmanagedType.LPWStr)] string appRegistryName );
void ClearUserAssociations();
}
public enum ASSOCIATIONLEVEL
{
AL_MACHINE,
AL_EFFECTIVE,
AL_USER,
};
public enum ASSOCIATIONTYPE
{
AT_FILEEXTENSION,
AT_URLPROTOCOL,
AT_STARTMENUCLIENT,
AT_MIMETYPE,
};
Courtesy MSDN and this blog post example for IApplicationAssociationRegistration.
A: Set the status code and description, then return null for the result. Only the first two are required, but since the result will not be sent, your method should not return a result. For example:
[System.ServiceModel.OperationContract]
[System.ServiceModel.Web.WebInvoke(Method = "GET", ResponseFormat = System.ServiceModel.Web.WebMessageFormat.Json)]
public Duo.DuoResult<Duo.Authentication.ResultTime> ping()
{
var requestUri = System.ServiceModel.Web.WebOperationContext.Current.IncomingRequest.UriTemplateMatch.RequestUri;
Duo.DuoResult<Duo.Authentication.ResultTime> result = null;
result = new Duo.DuoResult<Duo.Authentication.ResultTime>();
result.methodResult = new Authentication.ResultTime();
result.methodResult.utcTime = DateTime.UtcNow;
result.methodSucceeded = "OK";
bool simulateForbiddenReturn = false;
if (simulateForbiddenReturn)
{
System.ServiceModel.Web.WebOperationContext.Current.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.Forbidden;
System.ServiceModel.Web.WebOperationContext.Current.OutgoingResponse.StatusDescription = "Dlux test";
return null;
}
return result;
}
A: Declare the method as usual with WebInvoke, but write it to accept a single parameter of type Stream. Then, for example, if you expect those bytes to be text as with the Duo Auth API, use a StreamReader to decode them and process them as you need. Also, set the BodyStyle attribute so WCF knows the response is JSON, but the request is raw. For example:
[System.ServiceModel.OperationContract]
[System.ServiceModel.Web.WebInvoke(Method = "POST", BodyStyle=System.ServiceModel.Web.WebMessageBodyStyle.WrappedResponse)]
public Duo.DuoResult<Duo.Authentication.ResultAuthenticationCapabilities> preauth(System.IO.Stream pStream)
{
var requestUri = System.ServiceModel.Web.WebOperationContext.Current.IncomingRequest.UriTemplateMatch.RequestUri;
var headers = System.ServiceModel.Web.WebOperationContext.Current.IncomingRequest.Headers;
var myReader = new System.IO.StreamReader(pStream);
var inputText = myReader.ReadToEnd();
var result = new Duo.DuoResult<Duo.Authentication.ResultAuthenticationCapabilities>();
result.methodResult = new Authentication.ResultAuthenticationCapabilities();
result.methodResult.statusMessage = "This is the status";
result.methodResult.mobileEnrollmentUrl = new Uri("http://www.nowhere.com");
result.methodSucceeded = "OK";
return result;
}
A: Run your app elevated on Vista+ or with local administrative rights on XP/Server 2003. The app is doing something that needs more rights than it has and is failing with a security exception.
A: You are using TimeSpan.MinValue - use TimeSpan.Zero for 0 instead.
A: This concept does not quite exactly exist in C# because you can't delete an object, but you can implement IDisposable and a finalizer to accomplish what is intended. Which is more appropriate depends on what is being done. In general, IDisposable is recommended. Do the following:
1. Add a cleaned up bool to the class, typically called disposed, initialized to false.
2. Write a single cleanup function, typically called Dispose(bool), structured as follows:
public void Dispose( bool disposing )
{
if (!disposed)
{
// Do all necessary cleanup
// If you need to differentiate where the call came from, check disposing. Typically unnecessary
// unless you're cleaning up unmanaged stuff when Dispose is called and everything else later.
disposed = true;
}
}
3. Implement IDisposable.Dispose to cleanup and skip the destructor with code like this:
Dispose(true);
GC.SuppressFinalize(this);
4. Implement a destructor (also called a Finalizer) with the following code:
Dispose(false).
A: No, it is specifically forbidden by the language spec. Write a generic that exposes T as a member instead, or derive a class from T.
A: C# does not encourage this - its perspective is that it owns the memory representation of a thing. This can be done for structs using unsafe code, as in the following:
unsafe
{
MyStructType sampleStruct = new MyStructType();
MyStructType* sampleStructManagedPtr = &sampleStruct;
byte* sampleStructRawManagedPtr = (byte*) sampleStructManagedPtr;
byte[] targetArray = new byte[System.Runtime.InterOp.Marshal.SizeOf(sampleStruct)];
int currTargetByte = 0;
for (int currSourceByte = 0; currSourceByte++; currSourceByte < System.Runtime.InterOp.Marshal.SizeOf(sampleStruct))
{
targetArray[currTargetByte] = *(sampleStructRawManagedPtr + currSourceByte);
currTargetByte += 1;
}
}
Note the above code is simple for purposes of illustration. Anything concerned with speed should use long*'s to do qword (8-byte) transfers. Object memcpys cannot be done via C# as the compiler will report a CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type. However, this could probably be accomplished via IL, but again with the caveat that the runtime owns this representation and so it may change between versions, across platforms, or for other reasons.
A: This is a more complicated questions than it seems. In C#, there are two kinds of memory: managed and unmanaged. All managed code can only work directly with managed memory.
a. To do a memcpy between two unmanaged regions, use IntPtr's to refer to the regions and an unmanaged method or Windows DLL export, such as CopyMemory, to move the bytes.
b. To do an unmanaged/managed memcpy, use System.Runtime.Interop.Marshal.Copy
c. To do a managed-to-managed memcpy, you must implement it yourself by using unsafe pointers. Note that you cannot copy objects as you would in C++, but you can copy blittable types, which are structs or arrays of structs. Alternatively, if you are comfortable writing in IL, the NET version of assembly, there is a cpblk instruction that is the exact equivalent. For performance tests on memcpy methods in NET, see http://code4k.blogspot.com/2010/10/high-performance-memcpy-gotchas-in-c.html. In summary, using DDWORD transfers, performance is similar in x86/x64 modes, although cpblk is much faster in x64 than x86.
d. To do a managed-to-managed copy of arrays of primitives in a bytewise fashion or access their byte representation directly, see System.Buffer.
A: This can't be done. C# appears to treat generic structs like objects. Make the struct non-generic.
A: There is no way to force a method to be inlined, but you can request a class or method to be inlined. NET has several restrictions on what methods may and may not be inlined. In NET 4, an entire class can be requested to be inlined by marking it with [System.Runtime.TargetedPatchingOptOut]. In NET 4.5, it is possible to override the maximum method size criteria by marking a method with [System.Runtime.MethodImpl(MethodImplOptions.AggressiveInlining)]. The inline exclusion criteria are the following:
Methods marked with MethodImplOptions.NoInlining
Methods larger than 32 bytes of IL
Virtual methods
Methods that take a large value type as a parameter
Methods on MarshalByRef classes
Methods with complicated flowgraphs
Methods meeting other, more exotic criteria
The NET 4.5 AgressiveInline attribute overrides only the maximum length exclusion criteria.
A: Use multiple casts, use System.Convert.To<Primitive>, or change the type of the source object being cast to dynamic instead. This is by design for performance reasons. The C# cast operator is limited to unboxing value types only to their original type, because the code required to always fully analyze an object for conversion is very expensive. The final solution, a dynamic object, is the most powerful, but also the most expensive. For more information, see this blog entry.
A: Change the initial assignment of the struct to use the interface type. C#'s autoboxing clones the original struct in the cast assignment and the method call is made on the autoboxed clone, which is discarded. Consequently, this code - where promote is an IPromotion method that increments a Grade member from 65 to 66, and ToString reports the Grade - reports 65 twice instead of 65, then 66:
Employee employee = new Employee("Cool Guy", 65);
IPromotion p = employee;
Console.WriteLine(employee);
p.promote();
Console.WriteLine(employee);
To resolve this, either change the struct to a class, or change the initial assignment to the interface type (IPromotion employee = new Employee...) so the autoboxing never occurs. Courtesy this MSDN blog.
A: It depends on what you mean and what version of NET is used. If for WPF's INotifyPropertyChanged, use NET 4.5 with C# 5.0's CallerMemberName attribute (see below for more information). If you only need to identify the currently running method, use System.Reflection.MethodBase.GetCurrentMethod(). This is by far the fastest method with a performance penalty of only approximately 35x (one order of magnitude times a small constant). If you need to go above the current stack frame for any reason - for example, to determine the caller to the current method, then the impact is considerably higher, by another order of magnitude and small constant. Consequently, the performance impact is approximately 780x for obtaining stack traces. Finally, if you also need to identify the filename, line number, and column number (fNeedFileInfo = true), this is 50% slower again. In NET 2.0, GetStackTrace was considerably faster by orders of magnitude. See this link.
Dynamic method name identification is often used in WPF to automate the implementation of INotifyPropertyChanged, eliminating magic strings, or in remote servers for logging. Note that in the former case, the property setters must be decorated with [MethodImplAttribute(MethodImplOptions.NoInlining)] or the stack trace analysis can fail in Release builds. The following numbers illustrate the impact of current method identification on code performance. The test was to change the values of 3 properties on a single object 100,000 times. The property data types were double, int, and string; the new values were constants; and each setter was decorated with NoInlining . Each property setter also called RaisePropertyChanged, to make this code as similar to real code as possible. This was performed on NET 4.0 using a Debug build on a quad-core Intel i7 950 (hyperthreaded).
If you need higher performance, RtlCaptureStackBackTrace may provide a solution. According to this MSDN forum posting, the method provides very fast performance in debug builds for information on the current call stack only.
For more information on automatic implementations of WPF's INotifyPropertyChanged interface, see this blog posting. This appears to be the most comprehensive writeup on this subject to date.
The fastest ways to identify the current method for IPropertyChanged notification setters are:
Code generation/modification at build time. This is referred to as "code weaving" or sometimes as aspect-oriented programming.
The ActiveSharp toolkit on CodePlex. This uses field offsets from THIS paired with method disassembly to determine what fields are set by property setters, thus constructing a map of field offsets->property names. This well within an order of magnitude of using hard-coded strings (e.g., .
In C# 5.0, use the [CallerMemberName] attribute in a utility method called by the setter. This has zero overhead, but is not yet available as a released product.
Note that in the vast majority of cases, the overhead of StackTrace methods is irrelevant to the application. It does add 0.12 ms to a property setter call, but unless the code is setting more than, say, 100 properties per second, the overhead is irrelevant.
A: Cast it to an IDictionary<string, object> and use that.
A: MethodBase.Invoke is significantly slower at around 40 times slower. This is a constant slowdown, not a first-time-run impact, as is common with reflection.
A: Use a different API. AssemblyResolve is not like old-style Win32 APIs - it is only called for assemblies that could not be resolved, not for all assemblies. Consequently, there is no need for the old-style logic of if (!Assembly.Load()) { ...retry intelligently...}, since this handler only receives calls for assemblies that NET could not load. This means the handler must ultimately produce a filename. All Assembly.Load* calls that are not recursive use a filename, either directly or indirectly. These are LoadFile, Load(byte[]), and LoadFrom.
A: Use a delegate to fix the call signature, then call via the delegate. Do not use MethodBase.Invoke. This looses the flexibility of a dynamic method signature in exchange for performance. To mitigate the impact of this, implement and use the dynamically generated class with a dynamic object: derive the dynamically generated class from System.Dynamic.ExpandoObject, and store/use it in a dynamic variable. For most cases, however, MethodBase.Invoke is quite fast enough.
A: You can't - the C# language specification does not support this. The closest you can come is to declare the class internal, which allows any class in that assembly to access it.
A: There are only two ways of accomplishing this:
1. Nested Class
a. Declare an interface for all publicly-accessible methods/properties of the semi-private class.
b. Define the semi-private class as a private nested class with a public constructor.
c. Create and return instances in the containing class as needed.
2. Static Factory
a. Declare the semi-private class with a private constructor.
b. Implement static constructor methods to construct instances of the class or add them to exiting objects.
A: Use fixed-type delegates. The reflection API is slow due to the typeless nature of the APIs. See the FasterFlect project - it reduces member access/invocation penalties from 200x times to 1.5 average, 2.0 maximum.
A: There is no direct way to do this, but there are a couple workarounds. In all cases, you must check the type of the generic parameter and handle it by-type individually, but this is the intention of partial template specialization anyway. Note that none of the workarounds has zero performance impact as with C++ partial template specialization.
1. Cast to specific type through a cast to object.
For example, say you need to store a value in one of several variable arrays depending on the type of the variable. After detecting the specific type, you turn the generic parameter into a concrete type by casting it to object, then to the concrete type. This takes advantage of C#'s autoboxing and unboxing capabilities. This imparts a performance penalty of 8x the time of a strongly typed function.
public void SetVariableValueOldOk<Tvalue>( int variableStorageElementNo, Tvalue newValue ) { if (typeof(Tvalue) == typeof(double)) variableStorageDouble[variableStorageElementNo] = (double) (object) newValue; else if (typeof(Tvalue) == typeof(int)) variableStorageInt[variableStorageElementNo] = (int) (object) newValue; // Handle other types ...
}
2. Use pointers to take the address of the generic parameters
This functions as above, but manually pins the generic parameter by using a little-known trick of obtaining a second GC handle to an existing object. It is then possible to get the address of the object, bypassing the compiler's limitation on doing so for managed types. This has only been tested for value-types. Unfortunately, the overhead of the GCHandle calls render this method no faster than the above.
public unsafe void SetVariableValue<Tvalue>( int variableStorageElementNo, Tvalue newValue ) { IntPtr valuePointer; double* valuePointerDouble; int* valuePointerInt; System.Runtime.InteropServices.GCHandle genericObjectHandle; genericObjectHandle = System.Runtime.InteropServices.GCHandle.Alloc(newValue, System.Runtime.InteropServices.GCHandleType.Pinned); valuePointer = genericObjectHandle.AddrOfPinnedObject(); if (typeof(Tvalue) == typeof(double)) { valuePointerDouble = (double*) valuePointer; variableStorageDouble[variableStorageElementNo] = *valuePointerDouble; } else if (typeof(Tvalue) == typeof(int)) { valuePointerInt = (int*) valuePointer; variableStorageInt[variableStorageElementNo] = *valuePointerInt; } genericObjectHandle.Free(); }
A: A call to typeof is approximately 14x more expensive than setting a value in a single-dimensional array.
A: Not in the way that is intended by this question - unfortunately, the MSDN description of shadow copy is vague. AppDomain shadow copy does NOT permit the in-memory assembly used in an AppDomain to be updated. What it does instead is permit the install fileset to be modified, by making a copy of nearly all an application's assemblies to a temp directory at app startup, assuming the author follows a specific pattern in the application design. At least one assembly must provide the support for this, and consequently cannot be updated. The Shadow Copy feature is intended for use by service-oriented programs such as servers, where the server core is hosted in a separate replaceable assembly and run in a child AppDomain. The program must include a shell with three responsibilities:
Run the server core in a child AppDomain with ShadowCopy enabled for a specified directory containing the core assembly(ies).
Route client requests to the appropriate AppDomain and server responses back to those clients. Nearly always, this is accomplished by holding a reference to the current child AppDomain to use and routing all new client connections to it.
Monitor the special directory containing the core assembly(ies), and when it sees updates, create a new AppDomain using the new assemblies.
For reference, see this old but authoritative MSDN blog that clearly spells this out at the end.
A: No, the Microsoft C# compiler only generates managed code. It cannot generate code that does not require the NET runtime services to operate. However, you can write methods that use pointers. This is called unsafe code. You can also pass a pointer to a managed delegate to an unmanaged function, such as a Win32 API like EnumWindows. The NET runtime will automatically lock the method code and marshal the method pointer to a native pointer. Doing this introduces the unobvious problem that the delegate may be cleaned up unexpectedly. This happens when you pass a delegate that must remain registered past the lifespan of the current method call or context. Resolving this is easy: store a reference to the delegate in an object with sufficient lifespan.
A: It depends.
Using only a few thousand values at a time: Use System.Numerics.BigInteger. This has the best performance of any extended-length integer I have tested, C# and C++.
Using hundreds of thousands or more values at a time: It depends again:
Performance of multiply/divide not that important: Use the Softfluent Int128 class. It is posted on CodePlex and it's license is commercial-friendly (Microsoft Public License).
Need high-speed multiply/divide: Roll your own. Easiest way to do is to either fix the multiply/divide in the Softfluent class. See the Mono source for a good-speed BigInteger whose operations are nearly as fast as the Microsoft implementation.
There are significant performance differences between implementations. A key issue is that most Int128 implementations are really arbitrarily-long integer classes originating from cryptography or game programming, which hurts their performance in this case. Here's a performance comparison of several extended-size integer libraries for 128-bit (16 byte) integers versus int64 operations. The table shows the time of the operation in multiples of the time for the same operation implemented using int64s. All operations used the same 4-digit numbers. This test was not extremely rigorous, but it is accurate enough for the differences it encountered.
*None of these libraries actually implement this function - they all convert the big integer to a number, then use a double string parsing routine to get the double, thus the extreme slowness
**Unsupported, you must create your own
***No significant difference when using different memory allocators, internal APIs, or provided classes implementations
A: You can't in Windows 7 and previous. All CLR types are actually compiled to IL, not native code. The Visual C++ IDE/debugger goes to considerable effort to make everything appear native, but it is not. You can partially workaround this by calling an assembly function. The CLR will automatically perform a managed/unmanaged transition at the CALL instruction - the Visual Studio IDE will not indicate that this is done or allow you to trace through it. Consequently, the expense of this transition is hidden. The overhead is quite low and only significant if the execution time of your method is on the order of 1-10 function calls, as in the case of the x86 assembly instructions to perform 128-bit operations. In this case, the overhead may exceed the time of your method by several times and is unavoidable.
C++/CLI actually compiles to CIL #1
C++/CLI actually compiles to CIL #2
In Windows 8 and above, however, you can accomplish this by writing a Windows Runtime Component that can be projected into .NET and used from there. This is not a feature of the .NET framework, it is a feature of the new Windows Runtime API in Windows 8. Consequently, it is unlikely to be backported to Windows 7 or older OS's. One reference, though not the best, on this is here.
A: You can't, and Visual Studio will hide the transition from you as you trace through the code in the debugger. For example, if you enable disassembly while stepping through a function, a single-step at the assembly CALL instruction will go directly to the code for that function. The only indication that a managed->native transition took place is the addition of a [Managed-to-native] item at the top of the call stack. Consider re-implementing the routine using only C++ code that is supported by the CLR - this means no compiler intrinsics either. While slower, the total time will likely be less than the less efficient implement + managed->unmanaged transition time.
A: Call System.BitConverter.IsLittleEndian. This assumes memory is byte-addressable, which is normally the case. However, some memory is word-addressable, which can result in unexpected byte orderings, such as little-endian 16-bit.
A: Do the following:
1. Create an XmlSerializerNamespaces object and add all needed prefix/namespace mappings.
2. Set the Namespace attribute of the XmlRoot used for your class to the namespace it exists in (not the prefix)
A: In general, it is better to use DataContractSerializer than XmlSerializer. The XmlSerializer class should only be used when you need exact control of the XML generated or processed. This can be complicated by limitations of XmlSerializer, particularly in regard to custom collection types. The following rules illustrate how to map C# classes to XML via XmlSerializer. These rules should not be considered the only way to do things, particularly in the case of collections, but are the simplest approach most of the time.
1. Model each XML complex type or structure-like element as a class. A structure-like element is an element whose child elements store either primitive values or collections of primitive values.
2. Decorate the class members stored as an XML element with XmlElement. If necessary, use a more descriptive or meaningful name in the C# class and specify the ElementName attribute of XmlElement to connect it to the element name in the XML.
3. Decorate the class members stored as XML attributes with XmlAttribute. If necessary, use a more descriptive or meaningful name in the C# class and specify the AttributeName attribute of XmlElement to connect it to the element name in the XML.
4. To capture all attributes of an element not mapped by members decorated with XmlAttribute, create a single member of type XmlAttribute[] decorated with XmlAnyAttribute. If you need only the attribute values, this member can a string collection type instead, such as string[] or List<string>. This is not recommended if the class will be serialized as well due to the lack of attribute names.
5. To capture all child elements of an element not mapped by members decorated with XmlElement, create a single member of type XmlElement[] decorated with XmlAnyElement. Note that empty child elements with no attributes are ignored.
6. To capture the value (inner text) of an element that represents a primitive value and also has an attribute, create a class for the element with two members: one for the attribute decorated with XmlAttribute and one for the element contents decorated with XmlText.
7. There are many ways to map collections from XML to the class.
a. If the XML uses a plural/singular pattern, such as a <books> element that contains multiple <book> elements, create a class for the item, book in this case, then map the collection by creating a class member decorated with XmlArray("books") and XmlArrayItem("book"). For example, for the following XML:
<root>
<books>
<book>
<title>The Hitchhiker's Guide To The Galaxy</title>
<author>Douglas Adams</author>
</book>
<book>
<title>The C Programming Language</title>
<author>Brian Kerningham and Dennis Ritchie</author>
</book>
</books>
</root>
This can be mapped via the following C#:
[XmlType("root")]
public class Root
{
[XmlArray("books")]
[XmlArrayItem("book")]
public Book[] theBooks;
}
public class Book
{
[XmlElement(ElementName="title"))
public string title;
[XmlElement(ElementName="author"))
public string author;
}
This XML can also be modeled using the method in B, but it requires three classes instead of two: one for root, one for books, and one for book. That approach is not recommended.
b. If the XML uses a list of elements of the same type, map the collection by creating a class member of any valid collection type. For example, given the following XML:
<common_properties somethingcustom="zzz">
<e name="NCName" desc="String" type="string" lang="en-us" ro="false" unit="String" unit_ref="String" ci="0">text</e>
<e name="blub" ci="1" desc="Blubber factor">17</e>
</common_properties>
This can be modeled using the following C# code: This class also captures any other attributes not specifically mapped via XmlAttribute.
public class CommonProperties
{
[XmlElement(ElementName="e")]
public CommonPropertiesExtensionValue[] values;
}
public class CommonPropertiesExtensionValue
{
[XmlAttribute(AttributeName="name")]
public string name;
[XmlAttribute(AttributeName="desc")]
public string description;
[XmlAttribute(AttributeName="type")]
public string type;
[XmlAttribute(AttributeName="lang")]
public string language;
[XmlAttribute(AttributeName="ro")]
public string isReadOnly;
[XmlAttribute(AttributeName="unit")]
public string unit;
[XmlAttribute(AttributeName="unit_ref")]
public string unitReference;
[XmlAttribute(AttributeName="ci")]
public string creatorId;
[XmlAnyAttribute]
public System.Xml.XmlAttribute[] customAttributes;
[XmlText] public string value;
}
8. You must designate a single class as the root element for your file. Decorate this class with XmlRoot. The data type of this class is the type you specify when creating the XmlSerializer.
9. If the root element and all subelements exist within a namespace, specify this namespace via XmlRoot's Namespace attribute. If a subelement exists in a different namespace, specify that namespace by setting the Namespace property of the XmlElement attribute on the c# class member for that subelement. For example, in the example in 7b, if the e element existed in a namespace different from it's parent common_properties, this should be specified by modifying the XmlElement attribute on CommonProperties.values to add Namespace="http://whatever".
A: Add a XmlSerializerNamespaces member to the element marked [XmlRoot] and decorate the member with [XmlNamespaceDelcarations]. This will persist the namespace prefixes defined at the document root and normally resolves the issue. However, it is possible to define a namespace prefix or current namespace at any element of an XML file. To persist this information for serialization, it must be captured during deserialization. To do so, modify every class corresponding to an XML element by adding a XmlAttribute[] member decorated with [XmlAnyAttribute]. This will ensure that any element custom attributes are persisted and written back out at serialization time
A: Call XmlWriter.LookupPrefix, and if non-null, supply the prefix in the WriteAttributeString call. For example:
namespacePrefix = targetWriter.LookupPrefix(currCustomAttribute.NamespaceURI);
if (namespacePrefix != null)
targetWriter.WriteAttributeString(namespacePrefix, currCustomAttribute.LocalName, currCustomAttribute.NamespaceURI, currCustomAttribute.Value);
else
targetWriter.WriteAttributeString(currCustomAttribute.LocalName, currCustomAttribute.NamespaceURI, currCustomAttribute.Value);
A: Use an XPathDocument to get an XPathNavigator. This is approximately 30x faster than an XmlDocument's XPathNavigator. See this link for an illustrative study.
A: Get a copy of that schema and provide it to the reader in the XmlReader.Create call. To do so, specify an XmlReaderSettings object in the XmlReader.Create call and manually load the xml schema into that settings object, as in:
schemaStream = new FileStream(System.IO.Path.Combine(Path.GetDirectoryName(schemaName), "xml.xsd"), FileMode.Open, FileAccess.Read); newSchema = XmlSchema.Read(schemaStream, null); schemaStream.Dispose(); readerSettings.Schemas.Add(newSchema);
The MSDN documentation for XmlReader also suggests that the the XmlSchemaValidationFlag.AllowXmlAttributes will resolve this as well. In my testing, it did not, regardless of whether or not the "xml" namespace was declared by the XSD.
A: You don't. You can create a RESX element with a base64-'d copy of the file data, however. A RESX file is completely self-contained, with no references to other files, unlike the RC format. To achieve an effect similar to adding a binary resource stored in a file to an RC file, add the file to the Visual Studio project as an existing item, then set the Build Action to Embedded Resource. If this is a WPF project, the Build Action Resource can be used as well. The method used to load the file from resources varies slightly based on this type. For an example of loading an embedded resource, see this MSDN example.
A: Edit the *proj file directly and add a LogicalName element to the EmbeddedResource element whose name you want to customize. Set the element content to the name to use. For example:
<EmbeddedResource Include="XSD\xml.xsd">
<SubType>Designer</SubType>
<LogicalName>xsd\xml.xsd</LogicalName>
</EmbeddedResource>
A: No. The string used for the namespace is actually simply a prefix for embedded resource names. There are no actual namespaces used for embedded resources. The prefix is generated from the Visual Studio default namespace project setting. You can, however, specify names for the resources instead of using automatically generated names. See the question above for more information.
A: Yes. The XmlSerializer functions by dynamically creating an assembly at runtime and then executing that assembly. To debug the dynamically-generated assembly, add the following to your app.config:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
...
<system.diagnostics>
<switches>
<add name="XmlSerialization.Compilation" value="1" />
</switches>
</system.diagnostics>
...
</configuration>
Then you will be able to step into the Serialize/Deserialize calls. I've seen this many places on the web, most recently on Dominic Zukiewicz's blog.
A: Yes. Use the IL Disassembler installed with .NET. They will be listed under the MANIFEST element, normally at the top of the list. However, note that you must double-click the element to get the assembly list. The text window at the bottom of ILDisasm does NOT show the value of the selected item.
A: Use the .NET 4.0 version of SGen, located in "C:\Program Files\Microsoft SDKs\Windows\v7.0A\bin\NETFX 4.0 Tools". Visual Studio 2010 includes several versions of SGen, some of which are better than others. Credit this stackoverflow answer.
A: Use reflection to extract the "validator" field from the XmlReader. Cast this to System.Xml.Schema.XmlSchemaValidator, then call GetExpectedParticles().
A: No. This argument is used only by NetDataContractSerializer. DataContractSerializer doesn't even have an instance of StreamingContext. See the DataContractSerializer source code.
A: No. There is currently no clarification on when or if such support may be available from Microsoft. Note that some, reportedly about half, of WinRT APIs can be called from a desktop app in some way, though.
Paul Spiteri's Blog With References to MSDN Discussions
A: Call System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(targetType.TypeHandle). Static field and property initializers are run before the class static constructor. This method ensures the class constructor is run only once. Note if you reference a class static directly, from code, the runtime of course ensures it is initialized for you.
References: Slashdot discussion, C# language specification section 10.5.5.1.
A: You can't, but you can achieve the same effect via reflection. Change the argument to a Type object and add a string property/field name argument. You may also want an argument to clarify if a field or property is being referenced. Then use reflection to get the static field/property. Make sure to call RunClassConstructor first to ensure the target's initializer has run, or this is useless.
A: You don't. The NetDataContractSerializer has support that sounds very similar to DataContractSerializer's surrogates, but is effectively useless for most surrogates due to it's limitations. For example, you can't solve the problem of remoting an unserializable system type such as System.Type or XmlSchemaObject. In particular, the DataContractSerializer allows a caller to provide a substitute fully-built object to be serialized in place of another, and perform the reverse. This encapsulates three important capabilities:
1. The DataContractSerializer allows the caller to arbitrarily specify the type of object to substitute for the unserializable object X. Other instances of the same class as X can use different types for the surrogate if needed.
2. The surrogate is serialized and deserialized using the standard DataContractSerializer methods.
3. The DataContractSerializer permits the surrogate specifier/unwrapper to initialize the surrogate and reconstruct the original via user specified code.
The NetDataContractSerializer does support an interface called ISerializationSurrogate, but this has many limitations:
1. It cannot change the type of the object serialized in the stream/deserialized from the stream.
2. The surrogate must implement ISerializable-style serialization.
3. It requires a parameterless constructor, because the NetDataContractSerializer owns object construction.
The type of object can only be changed at deserialization time. This is done by specifying a Binder and overriding BindToType. However, only the type of object created can be changed - the binder cannot supply the object itself. Consequently, this requires the type specified to support deserialization, and if it were capable of that, there would be no point in many cases.
See this MSDN article for examples of NetDataContractSerializer surrogates.
A: Use one of the following options. There is no direct object invocation as in COM.
1. Implement a client/server system using .NET Remoting. Note this supports only Tcp and Http channels, although you can roll your own.
2. Implement a client/server system using System.ServiceModel.ServiceHost. This also supports NetNamedPipeBinding and a couple others.
3. Implement a WCF service in the other process. This is ultimately the same as .NET remoting.
4. Write some custom IPC mechanism.
5. If you launched the other process via a CreateDomain call, you can use a cross-domain delegate. See http://msdn.microsoft.com/en-us/library/ms173139%28VS.80%29.aspx for more information.
A: Do the following:
1. Get an Assembly object for the assembly where the class is defined.
2. Call the assembly's GetType method to get a type object. For example, xmlAssembly.GetType("System.Xml.XsdValidatingReader")
3. Use GetConstructor to get the constructor method, specifying the argument types. GetConstructors will not return a list of all constructors in this usage - you must know what you are looking for.
4. Call the constructor method's Invoke. The constructed object is the return value.
See also the AccessPrivateWrapper, shown here.
A: Most services only need to know about startup and shutdown. This can be handled with code in the constructor and Dispose. For more than this, implement a custom ServiceHostFactory and add a Factory= attribute to the SVC file equal to the full name of the factory class. For more information, see msdn.
A: This is actually a normal exception that can be ignored, but by default Visual Studio's exception assistant breaks execution. The fix is to disable automatic break when this exception is thrown by
1. Navigate to Debug->Exceptions...
2. Expand "Managed Debugging Assistants"
3. Uncheck the NonComVisibleBaseClass Thrown option.
4. Click [Ok]
Courtesy this MSDN discussion.
A: No way known. Use the COM API instead, it simply fails immediately, and since it is COM, no exception is thrown.
A: Unknown. Inspector shows all properties as unsupported and no property in the enum appeared to work. However, window interactive state changes were returned. Switch to polling instead.