I have been following the guidelines from:
https://www.meziantou.net/stop-using-intptr-for-dealing-with-system-handles.htm
So basically I have now a wrapper class on top of my native code as follow:
public sealed class MyFileWrapper : IDisposable
{
private readonly MySafeHandle _handle;
// implement cstor and Dispose() as recommended
public int ReadFile(byte[] bytes, int numBytesToRead) {
int ret = NativeMethods.ReadFile(_handle...);
// ...
return numBytesRead;
}
}
with:
internal static class NativeMethods
{
[...]
// Take a SafeHandle in parameter instead of IntPtr
[DllImport("kernel32", SetLastError = true)]
internal extern static int ReadFile(MySafeHandle handle, byte[] bytes, int numBytesToRead, out int numBytesRead, IntPtr overlapped_MustBeZero);
[...]
}
What would be a good practice to unit test this ReadFile function (using Xunit) ? It seems like the static class NativeMethods is against good practice for unit testing, so I was wondering what people do in this case. It seems that hiding the implementation detail of MySafeHandle is part of the solution, so I suspect turning NativeMethods into an interface would expose too much of the low level.
Related
I'm trying to make a global settings provider for an application. It seemed bulky to have one object duplicated in so many different classes.
I've seeth this method work when the private static variable was something simple, like an integer, but I want it to work for QSettings—an object.
// settings.h
class Settings {
public:
static void Initialize();
static int serverRefreshRate();
private:
QSettings *settings;
};
// settings.cpp
#include "Server/settings.h"
void Settings::Initialize() {
Settings::settings = new QSettings(/* etc */);
}
int Settings::serverRefreshRate() {
return settings->value("server/refreshRate", 10000).toInt();
}
Is there a way I can achieve this, or am I going about it in the wrong way?
Thanks!
EDIT,
Firstly, it needed to be:
static QSettings *settings;
And I needed the following in the .cpp.
QSettings* Settings::settings = NULL;
I'm coding a business layer for an ASP.NET application. I've created database methods in my BLL as static. I've created public static Func variables to be compiled and used in several different methods, like this:
namespace BLL
public class User
{
public static Func<Context, variable, result> selectUser;
private static void CompileQuery()
{
if(selectUser == null)
{
selectUser = CompiledQuery.Compile......
}
}
public static UserClass Select(int id)
{
CompileQuery();
//uses selectUser
}
public static SomethingElse DoSomethingElse()
{
CompileQuery();
//also uses selectUser
}
}
It'll be used in ASP.NET layer like this:
using BLL;
private void AddUser()
{
UserClass user = User.Select(id);
}
My question is, since static variables are not thread-safe, is this a bad design decision? I'm thinking of either implementing a locking mechanism, which makes me think if it'd slow down the application, or using instantiated class approach which makes me wonder if query compiling would be beneficial. I'd appreciate any advice on this.
It should at least be read-only - and initialized on type load, like this:
public static readonly Func<Context, variable, result> selectUser =
CompileQuery(); // Or inline this...
private static Func<Context, variable, result> CompileQuery()
{
return CompiledQuery.Compile(...);
}
I'd probably make it a property myself, but otherwise it should be okay. Delegates themselves are immutable and threadsafe, so that shouldn't be a problem.
Doing it on type initialization means you don't need to worry about locking: the CLR guarantees that a type initializer is executed once and only once.
I have a client (created using ASMX "Add Web Reference"). The service is WCF. The signature of the methods varies for the client and the Service. I get some unwanted parameteres to the method.
Note: I have used IsRequired = true for DataMember.
Service: [OperationContract]
int GetInt();
Client: proxy.GetInt(out requiredResult, out resultBool);
Could you please help me to make the schame non-varying in both WCF clinet and non-WCF client? Do we have any best practices for that?
using System.ServiceModel;
using System.Runtime.Serialization;
namespace SimpleLibraryService
{
[ServiceContract(Namespace = "http://Lijo.Samples")]
public interface IElementaryService
{
[OperationContract]
int GetInt();
[OperationContract]
int SecondTestInt();
}
public class NameDecorator : IElementaryService
{
[DataMember(IsRequired=true)]
int resultIntVal = 1;
int firstVal = 1;
public int GetInt()
{
return firstVal;
}
public int SecondTestInt()
{
return resultIntVal;
}
}
}
Binding = "basicHttpBinding"
using NonWCFClient.WebServiceTEST;
namespace NonWCFClient
{
class Program
{
static void Main(string[] args)
{
NonWCFClient.WebServiceTEST.NameDecorator proxy = new NameDecorator();
int requiredResult =0;
bool resultBool = false;
proxy.GetInt(out requiredResult, out resultBool);
Console.WriteLine("GetInt___"+requiredResult.ToString() +"__" + resultBool.ToString());
int secondResult =0;
bool secondBool = false;
proxy.SecondTestInt(out secondResult, out secondBool);
Console.WriteLine("SecondTestInt___" + secondResult.ToString() + "__" + secondBool.ToString());
Console.ReadLine();
}
}
}
Please help..
Thanks
Lijo
I don't think you can do much to make this "non-varying" - that's just the way the ASMX client side stuff gets generated from the WCF service. Each client-side stack is a bit different from the other, and might interpret the service contract in the WSDL in a slightly different manner. Not much you can do about that.....
If you don't want this - create a WCF client instead.
A remark on the side:
public class NameDecorator : IElementaryService
{
[DataMember(IsRequired=true)]
int resultIntVal = 1;
This is very strange how you're trying to put a DataMember (a field that should be serialized across for the service) into the class that implements the service.....
You should keep your service contract (interface IElementaryService), service implementation (class NameDecorator) and your data contracts (other classes) separate - do not mix data contract and service implementation - this is sure to backfire somehow....
This only clears items in the user cache:
public static void ClearCache()
{
foreach (DictionaryEntry entry in HttpRuntime.Cache)
{
HttpRuntime.Cache.Remove(entry.Key.ToString());
}
}
Is there any way to access the kernel cache as well?
Clarification: I want to print the keys of all items in the kernel cache, and as a bonus I'd like to be able to clear the kernel cache from a C# method as well.
Yep, it's possible to programmatically enumerate and remove items from IIS's kernel cache.
Caveats:
non-trivial text parsing requred for enumeration
lots of ugly P/Invoke required for removal
Also, you'll need at least Medium Trust (and probably Full Trust) to do the things below.
Removal won't work in IIS's integrated pipeline mode.
Enumeration probably won't work on IIS6
Enumeration:
The only documented way I know to enumerate the IIS kernel cache is a command-line app available in IIS7 and above (although you might be able to copy the NETSH helper DLL from V7 onto a V6 system-- haven't tried it).
netsh http show cachestate
See MSDN Documentation of the show cachestate command for more details. You could turn this into an "API" by executing the process and parsing the text results.
Big Caveat: I've never seen this command-line app actually return anything on my server, even for apps running in Classic mode. Not sure why-- but the app does work as I can see from other postings online. (e.g. http://chrison.net/ViewingTheKernelCache.aspx)
If you're horribly allergic to process creation and feeling ambitious, NETSH commands are implemented by DLL's with a documented Win32 interface, so you could write code which pretends it's NETSH.exe and calls into IIS's NETSH helper DLL directly. You can use the documentation on MSDN as a starting point for this approach. Warning: impersonating NETSH is non-trivially hard since the interface is 2-way: NETSH calls into the DLL and the DLL calls back into NETSH. And you'd still have to parse text output since the NETSH interface is text-based, not object-based like PowerShell or WMI. If it were me, I'd just spawn a NETSH process instead. ;-)
It's possible that the IIS7 PowerShell snapin may support this functionality in the future (meaning easier programmatic access than the hacks above), but AFAIK only NETSH supports this feature today.
Invalidation:
I've got good news and bad news for you.
The good news: Once you know the URL of the item you want to yank from IIS's kernel cache, there's a Win32 API available to remove it on IIS6 and above. This can be called from C# via P/Invoke (harder) or by putting the call in a managed C++ wrapper DLL. See HSE_REQ_GET_CACHE_INVALIDATION_CALLBACK on MSDN for details.
I took a stab at the code required (attached below). Warning: it's ugly and untested-- it doesn't crash my IIS but (see above) I can't figure out how to get cache enumeration working so I can't actually call it with a valid URL to pull from the cache. If you can get enumeration working, then plugging in a valid URL (and hence testing this code) should be easy.
The bad news:
as you can guess from the code sample, it won't work on IIS7's integrated pipeline mode, only in Classic mode (or IIS6, of course) where ASP.NET runs as an ISAPI and has access to ISAPI functions
messing with private fields is a big hack and may break in a new version
P/Invoke is hard to deal with and requires (I believe) full trust
Here's some code:
using System;
using System.Web;
using System.Reflection;
using System.Runtime.InteropServices;
public partial class Test : System.Web.UI.Page
{
/// Return Type: BOOL->int
public delegate int GetServerVariable();
/// Return Type: BOOL->int
public delegate int WriteClient();
/// Return Type: BOOL->int
public delegate int ReadClient();
/// Return Type: BOOL->int
public delegate int ServerSupportFunction();
/// Return Type: BOOL->int
public delegate int EXTENSION_CONTROL_BLOCK_GetServerVariable();
/// Return Type: BOOL->int
public delegate int EXTENSION_CONTROL_BLOCK_WriteClient();
/// Return Type: BOOL->int
public delegate int EXTENSION_CONTROL_BLOCK_ReadClient();
/// Return Type: BOOL->int
public delegate int EXTENSION_CONTROL_BLOCK_ServerSupportFunction();
public static readonly int HSE_LOG_BUFFER_LEN = 80;
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential, CharSet = System.Runtime.InteropServices.CharSet.Ansi)]
public struct EXTENSION_CONTROL_BLOCK
{
/// DWORD->unsigned int
public uint cbSize;
/// DWORD->unsigned int
public uint dwVersion;
/// DWORD->unsigned int
public uint connID;
/// DWORD->unsigned int
public uint dwHttpStatusCode;
/// CHAR[HSE_LOG_BUFFER_LEN]
[System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValTStr, SizeConst = 80 /*HSE_LOG_BUFFER_LEN*/)]
public string lpszLogData;
/// LPSTR->CHAR*
public System.IntPtr lpszMethod;
/// LPSTR->CHAR*
public System.IntPtr lpszQueryString;
/// LPSTR->CHAR*
public System.IntPtr lpszPathInfo;
/// LPSTR->CHAR*
public System.IntPtr lpszPathTranslated;
/// DWORD->unsigned int
public uint cbTotalBytes;
/// DWORD->unsigned int
public uint cbAvailable;
/// LPBYTE->BYTE*
public System.IntPtr lpbData;
/// LPSTR->CHAR*
public System.IntPtr lpszContentType;
/// EXTENSION_CONTROL_BLOCK_GetServerVariable
public EXTENSION_CONTROL_BLOCK_GetServerVariable GetServerVariable;
/// EXTENSION_CONTROL_BLOCK_WriteClient
public EXTENSION_CONTROL_BLOCK_WriteClient WriteClient;
/// EXTENSION_CONTROL_BLOCK_ReadClient
public EXTENSION_CONTROL_BLOCK_ReadClient ReadClient;
/// EXTENSION_CONTROL_BLOCK_ServerSupportFunction
// changed to specific signiature for invalidation callback
public ServerSupportFunction_HSE_REQ_GET_CACHE_INVALIDATION_CALLBACK ServerSupportFunction;
}
/// Return Type: BOOL->int
///ConnID: DWORD->unsigned int
///dwServerSupportFunction: DWORD->unsigned int
///lpvBuffer: LPVOID->void*
///lpdwSize: LPDWORD->DWORD*
///lpdwDataType: LPDWORD->DWORD*
[return: System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.Bool)]
public delegate bool ServerSupportFunction_HSE_REQ_GET_CACHE_INVALIDATION_CALLBACK(
uint ConnID,
uint dwServerSupportFunction, // must be HSE_REQ_GET_CACHE_INVALIDATION_CALLBACK
out Callback_HSE_REQ_GET_CACHE_INVALIDATION_CALLBACK lpvBuffer,
out uint lpdwSize,
out uint lpdwDataType);
public readonly uint HSE_REQ_GET_CACHE_INVALIDATION_CALLBACK = 1040;
// typedef HRESULT (WINAPI * PFN_HSE_CACHE_INVALIDATION_CALLBACK)(WCHAR *pszUrl);
[return: System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.Bool)]
public delegate bool Callback_HSE_REQ_GET_CACHE_INVALIDATION_CALLBACK(
[MarshalAs(UnmanagedType.LPWStr)]string url);
object GetField (Type t, object o, string fieldName)
{
FieldInfo fld = t.GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic);
return fld == null ? null : fld.GetValue(o);
}
protected void Page_Load(object sender, EventArgs e)
{
// first, get the ECB from the ISAPIWorkerRequest
var ctx = HttpContext.Current;
HttpWorkerRequest wr = (HttpWorkerRequest) GetField(typeof(HttpContext), ctx, "_wr");
IntPtr ecbPtr = IntPtr.Zero;
for (var t = wr.GetType(); t != null && t != typeof(object); t = t.BaseType)
{
object o = GetField(t, wr, "_ecb");
if (o != null)
{
ecbPtr = (IntPtr)o;
break;
}
}
// now call the ECB callback function to remove the item from cache
if (ecbPtr != IntPtr.Zero)
{
EXTENSION_CONTROL_BLOCK ecb = (EXTENSION_CONTROL_BLOCK)Marshal.PtrToStructure(
ecbPtr, typeof(EXTENSION_CONTROL_BLOCK));
uint dummy1, dummy2;
Callback_HSE_REQ_GET_CACHE_INVALIDATION_CALLBACK invalidationCallback;
ecb.ServerSupportFunction(ecb.connID,
HSE_REQ_GET_CACHE_INVALIDATION_CALLBACK,
out invalidationCallback,
out dummy1,
out dummy2);
bool success = invalidationCallback("/this/is/a/test");
}
}
}
From the discussion link you provided, it appears that the cache method or property exists but is protected or private so you can't access it.
Normally, you should stay away from using methods that are not part of the public API, but if you want to access them, use Reflection. With reflection, you can call private methods and get or set private properties and fields.
I have two Cairngorm MVC Flex applications (a full version and lite version of the same app) that share many Classes. I have put these Classes into a Flex Library Project that compiles as an SWC. Both applications use some static String constants. Right now, I am storing these in the ModelLocator:
package model
{
[Bindable]
public class ModelLocator
{
public static var __instance:ModelLocator = null;
public static const SUCCESS:String = "success";
public static const FAILURE:String = "failure";
public static const RUNNING:String = "running";
...
}
}
This just doesn't seem like the best place to store these constants, especially now that they are used by both applications, and I have setup each application to have its own ModelLocator Class. Plus this is not the purpose of the ModelLocator Class.
What would be a good way to store these constants in my shared Library?
Should I just create a Class like this?:
package
{
[Bindable]
public class Constants
{
public static const SUCCESS:String = "success";
public static const FAILURE:String = "failure";
public static const RUNNING:String = "running";
}
}
and then reference it like this:
if (value == Constant.SUCCESS)
...
I'd say organize the constants by logical meaning, instead of a single Constants class.
Say you have the 3 you show as some kind of task state, and you have some more that are used as error codes for file access (just making stuff up here):
public class TaskStates {
public static const SUCCESS:String = "success";
public static const FAILURE:String = "failure";
public static const RUNNING:String = "running";
}
public class FileErrors {
public static const FILE_NOT_FOUND:String = "filenotfound";
public static const INVALID_FORMAT:String = "invalidformat";
public static const READ_ONLY:String = "readonly";
}
I find this makes it easier to document what the expected values are for something. Instead of saying "Returns either SUCCESS, FAILURE, RUNNING, ...", you can just say "Returns one of the TaskState.* values).
You could put all these in a single package for constants, or you could have the constant classes live in the same package as the classes that use them.