问:
How to dispose of a NET COM interop object on Release()
I have a COM object written in managed code (C++/CLI).  I am using that object in standard C++.

How do I force my COM object's destructor to be called immediately when the COM object is released?  If that's not possible, call I have Release() call a MyDispose() method on my COM object?

My code to declare the object (C++/CLI):

```
    [Guid("57ED5388-blahblah")]
    [InterfaceType(ComInterfaceType::InterfaceIsIDispatch)]
    [ComVisible(true)]
    public interface class IFoo
    {
        void Doit();
    };

    [Guid("417E5293-blahblah")]
    [ClassInterface(ClassInterfaceType::None)]
    [ComVisible(true)]
    public ref class Foo : IFoo
    {
    public:
        void MyDispose();
        ~Foo() {MyDispose();} // This is never called
        !Foo() {MyDispose();} // This is called by the garbage collector.
        virtual ULONG Release() {MyDispose();} // This is never called
        virtual void Doit();
    };
```

My code to use the object (native C++):

```
#import "..\\Debug\\Foo.tlb"
...
Bar::IFoo setup(__uuidof(Bar::Foo)); // This object comes from the .tlb.
setup.Doit();
setup->Release(); // explicit release, not really necessary since Bar::IFoo's destructor will call Release().
```

If I put a destructor method on my COM object, it is never called.  If I put a finalizer method, it is called when the garbage collector gets around to it.  If I explicitly call my Release() override it is never called.

I would really like it so that when my native Bar::IFoo object goes out of scope it automatically calls my .NET object's dispose code.  I would think I could do it by overriding the Release(), and if the object count = 0 then call MyDispose().  But apparently I'm not overriding Release() correctly because my Release() method is never called.

Obviously, I can make this happen by putting my MyDispose() method in the interface and requiring the people using my object to call MyDispose() before Release(), but it would be slicker if Release() just cleaned up the object.

Is it possible to force the .NET COM object's destructor, or some other method, to be called immediately when a COM object is released?

Googling on this issue gets me a lot of hits telling me to call System.Runtime.InteropServices.Marshal.ReleaseComObject(), but of course, that's how you tell .NET to release a COM object.  I want COM Release() to Dispose of a .NET object.

答:
I have a COM object written in managed code (C++/CLI). I am using that object in standard C++.
  How do I force my COM object's destructor to be called immediately when the COM object is released? If that's not possible, can I have Release() call a Dispose() (not MyDispose() - GBG) method on my (managed DotNet - GBG) COM object?

RE:  Forcing a deterministic release of resources bound by a DotNet COM Server when the client is unmanaged code.  These resource can be arranged to be released when the Garbage Collector collects the item, but that is not deterministic and such resources as file streams may not be released for hours or days for large memory systems where garbage collection is infrequent.

This is a common problem with COM Callable Wrappers (CCW's) as can be seen by another somewhat related thread at:  Is it possible to intercept (or be aware of) COM Reference counting on CLR objects exposed to COM.  in that case as in any case where one is writing their own COM client, no matter whether under managed or unmanaged code, is easy to solve just by a call to the IDisposable.Dispose() method as was done there.  However, that method would not work for (say) a DotNet COM codec class whose client may be the operating system itself and which client shouldn't have to be aware that the COM server is unmanaged or managed (DotNet).

One can implement the IDisposable.Dispose() pattern on the DotNet COM server as per the MSDN link:  http://msdn.microsoft.com/en-us/library/system.idisposable.aspx, but that won't do any good because the Dispose() method will never get called by the CCW.  Ideally, the implementation of the CCW's in mscoree.dll should really check for and call the IDisposable.Dispose() method if implemented as part of the CCW release and/or finalization/destructor.  I'm not sure why Microsoft did not do this, as having full access to the Assembly information they could easily determine if the DotNet COM Class supports IDisposable and just call Dispose() on final release if it does, and since this would be within the CCW, all the complexities about handling reference counting due to the extra interface reference could be avoided.

I can't see how this would "break" any existing code, as any client that is IDisposable aware could still call Dispose(), which if implemented according to the above template only effectively does anything on the first call.  Microsoft may be worried about a class being Disposed while there are still managed references to it that wouldn't know about it being Disposed until there start to be exceptions thrown by trying to use already disposed resources, but that is a potential problem for any improper use of the IDisposable interface even with only DotNet clients:  if there are multiple references to the same object instance and any one of them calls Dispose(), the others will find trying to use the required disposed resources cause exceptions.  For such cases, one should always put in guards using the disposing boolean (as per the IDisposable pattern template) or only reference the object through a common wrapper.

Since Microsoft hasn't done the required few lines of code in the implementation of CCW's in mscoree.dll, I wrote a wrapper around mscoree.dll that adds this extra functionality.  It is a little bit complex in that in order to control the creation of my wrapper around any instance of any DotNet COM Class, I need to also wrap the IClassFactory interface and aggregate the CCW instance in my "CCW_Wrapper" wrapper class.  This wrapper also supports further levels of aggregation from yet another outer class.  The code also does reference counting on instances of classes within the mscoree.dll implementation in use so as to be able to call FreeLibrary on mscoree.dll when there are no references (and LoadLibrary again if necessary later).  The code should also be multi threading friendly as is required for COM under Windows 7.  My C++ code is as follows:

EDITED 22 December 2010:  Eliminated one unnecessary parameter of COM_Wrapper constructor:

```<code>#include <windows.h>

HMODULE g_WrappedDLLInstance = NULL;
ULONG g_ObjectInstanceRefCnt = 0;

//the following is the C++ definition of the IDisposable interface
//using the GUID as per the managed definition, which never changes across
//DotNet versions as it represents a hash of the definition and its
//namespace, none of which can change by definition.
MIDL_INTERFACE("805D7A98-D4AF-3F0F-967F-E5CF45312D2C")
    IDisposable : public IDispatch {
    public:
        virtual VOID STDMETHODCALLTYPE Dispose() = 0;
    };

class CCW_Wrapper : public IUnknown {
public:
    // constructor and destructor
    CCW_Wrapper(
        __in IClassFactory *pClassFactory,
        __in IUnknown *pUnkOuter) :
            iWrappedIUnknown(nullptr),
            iOuterIUnknown(pUnkOuter),
            iWrappedIDisposable(nullptr),
            ready(FALSE),
            refcnt(0) {
        InterlockedIncrement(&g_ObjectInstanceRefCnt);
        if (!this->iOuterIUnknown)
            this->iOuterIUnknown = static_cast<IUnknown*>(this);
        pClassFactory->CreateInstance(
            this->iOuterIUnknown,
            IID_IUnknown,
            (LPVOID*)&this->iWrappedIUnknown);
        if (this->iWrappedIUnknown) {
            if (SUCCEEDED(this->iWrappedIUnknown->QueryInterface(__uuidof(IDisposable), (LPVOID*)&this->iWrappedIDisposable)))
                this->iOuterIUnknown->Release(); //to clear the reference count caused by the above.
        }
        this->ready = TRUE; //enable destruction of the object when release decrements to zero.
        //OUTER IUNKNOWN OBJECTS MUST ALSO PROTECT THEIR DESTRUCTORS IN SIMILAR MANNERS!!!!!
    }
    ~CCW_Wrapper() {
        this->ready = FALSE; //protect from re-entering this destructor when object released to zero.
        if (this->iWrappedIDisposable) {
            //the whole reason for this project!!!!!!!!
            this->iWrappedIDisposable->Dispose();
            //the following may be redundant, but to be sure...
            this->iOuterIUnknown->AddRef();
            this->iWrappedIDisposable->Release();
        }
        if (this->iWrappedIUnknown)
            this->iWrappedIUnknown->Release();
        if (!InterlockedDecrement(&g_ObjectInstanceRefCnt)) {
            //clear all global resources including the mutex, multithreading safe...
            HMODULE m = (HMODULE)InterlockedExchangePointer((PVOID*)&g_WrappedDLLInstance, (LPVOID)0);
            if (m)
                FreeLibrary(m);
        }
    }

    // IUnknown Interface
    STDMETHOD(QueryInterface)(REFIID riid, void **ppv) {
        if (ppv) {
            *ppv = nullptr;
            if (riid == IID_IUnknown) {
                *ppv = static_cast<IUnknown*>(this);
                this->AddRef();
                return S_OK;
            }
            else if (this->iWrappedIUnknown) {
                return this->iWrappedIUnknown->QueryInterface(riid, ppv);
            }
            return E_NOINTERFACE;
        }
        return E_INVALIDARG;
    }

    STDMETHOD_(ULONG, AddRef)() {
        return InterlockedIncrement(&this->refcnt);
    }

    STDMETHOD_(ULONG, Release)() {
        if (InterlockedDecrement(&this->refcnt))
            return this->refcnt;
        if (this->ready) //if not being constructed or destructed...
            delete this;
        return 0;
    }

private:
    IUnknown *iOuterIUnknown;
    IUnknown *iWrappedIUnknown;
    IDisposable *iWrappedIDisposable;
    BOOL ready;
    ULONG refcnt;
};

class ClassFactoryWrapper : public IClassFactory {
public:
    // constructor and destructor
    ClassFactoryWrapper(IClassFactory *icf) : wrappedFactory(icf), refcnt(0), lockcnt(0) {
        InterlockedIncrement(&g_ObjectInstanceRefCnt);
    }
    ~ClassFactoryWrapper() {
        if (wrappedFactory)
            wrappedFactory->Release();
        if (!InterlockedDecrement(&g_ObjectInstanceRefCnt)) {
            //clear all global resources, multithreading safe...
            HMODULE m = (HMODULE)InterlockedExchangePointer((PVOID*)&g_WrappedDLLInstance, (LPVOID)0);
            if (m)
                FreeLibrary(m);
        }
    }

    // IUnknown Interface
    STDMETHOD(QueryInterface)(REFIID riid, void **ppv) {
        if (ppv) {
            *ppv = nullptr;
            if (riid == IID_IUnknown) {
                *ppv = static_cast<IUnknown*>(this);
                this->AddRef();
            }
            else if (riid == IID_IClassFactory) {
                *ppv = static_cast<IClassFactory*>(this);
                this->AddRef();
            }
            else {
                return E_NOINTERFACE;
            }
            return S_OK;
        }
        return E_INVALIDARG;
    }

    STDMETHOD_(ULONG, AddRef)() {
        return InterlockedIncrement(&this->refcnt);
    }

    STDMETHOD_(ULONG, Release)() {
        if (InterlockedDecrement(&this->refcnt) || this->lockcnt)
            return this->refcnt;
        delete this;
        return 0;
    }

    // IClassFactory Interface
    STDMETHOD(CreateInstance)(IUnknown *pUnkOuter, REFIID riid, void **ppv) {
        HRESULT result = E_INVALIDARG;

        if (ppv) {
            *ppv = nullptr;
            if (pUnkOuter && (riid != IID_IUnknown))
                return result;
            CCW_Wrapper *oipm = new CCW_Wrapper(wrappedFactory, pUnkOuter);
            if (!oipm)
                return E_OUTOFMEMORY;
            if (FAILED(result = oipm->QueryInterface(riid, ppv)))
                delete oipm;
        }

        return result;
    }

    STDMETHOD(LockServer)(BOOL fLock) {
        if (fLock)
            InterlockedIncrement(&this->lockcnt);
        else {
            if (!InterlockedDecrement(&this->lockcnt) && !this->refcnt)
                delete this;
        }
        return wrappedFactory->LockServer(fLock);
    }

private:
    IClassFactory *wrappedFactory;
    ULONG refcnt;
    ULONG lockcnt;
};

STDAPI DllGetClassObject(__in REFCLSID rclsid, __in REFIID riid, __deref_out LPVOID FAR* ppv) {
    HRESULT result = E_INVALIDARG;

    if (ppv) {
        *ppv = nullptr;
        if ((riid != IID_IUnknown) && (riid != IID_IClassFactory))
            return E_NOINTERFACE;
        HMODULE hDLL = LoadLibrary(L"mscoree.dll");
        if (!hDLL)
            return E_UNEXPECTED;
        typedef HRESULT (__stdcall *pDllGetClassObject) (__in REFCLSID, __in REFIID, __out LPVOID *);
        pDllGetClassObject DllGetClassObject = (pDllGetClassObject)GetProcAddress(hDLL, "DllGetClassObject");
        if (!DllGetClassObject) {
            FreeLibrary(hDLL);
            return E_UNEXPECTED;
        }
        IClassFactory *icf = nullptr;
        if (FAILED(result = (DllGetClassObject)(rclsid, IID_IClassFactory, (LPVOID*)&icf))) {
            FreeLibrary(hDLL);
            return result;
        }
        ClassFactoryWrapper *cfw = new ClassFactoryWrapper(icf);
        if (!cfw) {
            icf->Release();
            FreeLibrary(hDLL);
            return E_OUTOFMEMORY;
        }
        //record the HMODULE instance in global variable for freeing later, multithreaded safe...
        hDLL = (HMODULE)InterlockedExchangePointer((PVOID*)&g_WrappedDLLInstance, (LPVOID)hDLL);
        if (hDLL)
            FreeLibrary(hDLL);
        if (FAILED(result = cfw->QueryInterface(IID_IClassFactory, ppv)))
            delete cfw; //will automatically free library and the held class factory reference if necessary.
    }
    return result;
}

extern "C"
HRESULT __stdcall DllCanUnloadNow(void) {
    if (g_ObjectInstanceRefCnt)
        return S_FALSE;
    return S_OK;
}

extern "C"
BOOL APIENTRY DllMain( HMODULE hModule,
                                                DWORD  ul_reason_for_call,
                                                LPVOID lpReserved ) {
    switch (ul_reason_for_call) {
        case DLL_PROCESS_ATTACH:
        case DLL_THREAD_ATTACH:
        case DLL_THREAD_DETACH:
        case DLL_PROCESS_DETACH:
            break;
    }
    return TRUE;
}
</code>```

A '.def' file is also required for the DLL as follows:

```<code>LIBRARY mscoreeCOM_DisposeWrapper

EXPORTS
    DllCanUnloadNow         PRIVATE
    DllGetClassObject       PRIVATE
</code>```

To use this source code, compile it into a DLL and install the DLL into the Windows SYSTEM folder, then have your installation program or your [COMRegisterFunction] method in your DotNet COM server modify the class registry entry for the InprocServer32 from mscoree.dll to the name of this wrapper (say mscoreeWrapper.dll).  It can be compiled under 32 and/or 64 bit, and for installation on 64-bit systems should have the 64-bit version put into the System folder and the 32-bit version put into the SysWOW64 folder; also, both the normal CLSID registration and the virtualized WOW6432 versions should be modified as to the InprocServer32 entries.  Some applications may require this wrapper DLL to be digitally signed to work seamlessly, which is a whole other subject.  If someone wants, I'll make a link to my compiled versions of these DLL's available here.

As I said, the required few lines (excluding the wrapper requirements) technique should really be incorporated into mscoree.dll.  Does anyone know how to contact someone within the appropriate department within Microsoft to make this suggestion?

EDITADD:  I have submitted a suggestion for the DotNet Framework to Microsoft Connect. This seems to be the best way of giving Microsoft feedback.

EDITADD2:  In implementing a workaround for this problem, I realized why MIcrosoft likely will not implement this "Auto calling of Dispose, if supported, when the CCW reference count drops to zero". In writing the workaround, I had to obtain a reference pointer to a COM interface on a managed object in order to pass it to a pure unmanaged COM method, and then had to Release() that reference count in order to not have the CCW strongly referencing the object and therefore causing a memory leak by never having it available for garbage collection. I did this because I know that decreasing a reference count to zero on a managed object currently only makes the CCW drop its strong reference to the object, making it eligible for garbage collection if there are no other references. However, if Microsoft implemented the Auto Dispose fix as I have suggested or if this code was in place wrapping the mscoree.dll functionality, this would trigger a Dispose() on the managed object when it wasn't wanted. For this particular case, I could "guard" the Dispose(bool disposing) virtual method to prevent the Dispose() happening, but for any existing code that uses this behaviour with the same assumption, including Microsoft's implementation of the DotNet Runtime Libraries, implementing this "fix" on the CCW would break that existing code.  This wrapper fix still applies for COM Servers one writes themselves and is aware of this side effect, as they can put the "guards" in place on the Dispose().

EDITADD 3:  In further work with this, I see that my suggestion to Microsoft is still valid and the problems of "breaking" existing code can be avoided by the fix that would call the IDisposable.Dispose() method on the object instance implementing the managed COM server if the interface exists only if a new custom attribute such as [AutoComDispose(true)], whose default value is false, is applied to the managed COM server class.  In this way, the programmer would choose to implement the functionality and the documentation on the new attribute would caution its use regarding having to "guard" the Dispose() method such as with a "artificial reference count" when there is a possibility of the Marshal.Release() method being called explicitly by in code used by the managed server or implicitly by calls to methods such as Marshal.GetObjectForIUnknown(), which in some cases can call QueryInterface and Release of the reference point if the ComObject is a managed object.

The main problem with this Answer is the complexity of installing it for use, as noted above.

Body:
I have a COM object written in managed code (C++/CLI).  I am using that object in standard C++.

How do I force my COM object's destructor to be called immediately when the COM object is released?  If that's not possible, call I have Release() call a MyDispose() method on my COM object?

My code to declare the object (C++/CLI):

    [Guid("57ED5388-blahblah")]
    [InterfaceType(ComInterfaceType::InterfaceIsIDispatch)]
    [ComVisible(true)]
    public interface class IFoo
    {
        void Doit();
    };

    [Guid("417E5293-blahblah")]
    [ClassInterface(ClassInterfaceType::None)]
    [ComVisible(true)]
    public ref class Foo : IFoo
    {
    public:
        void MyDispose();
        ~Foo() {MyDispose();} // This is never called
        !Foo() {MyDispose();} // This is called by the garbage collector.
        virtual ULONG Release() {MyDispose();} // This is never called
        virtual void Doit();
    };

My code to use the object (native C++):

#import "..\\Debug\\Foo.tlb"
...
Bar::IFoo setup(__uuidof(Bar::Foo)); // This object comes from the .tlb.
setup.Doit();
setup->Release(); // explicit release, not really necessary since Bar::IFoo's destructor will call Release().

If I put a destructor method on my COM object, it is never called.  If I put a finalizer method, it is called when the garbage collector gets around to it.  If I explicitly call my Release() override it is never called.

I would really like it so that when my native Bar::IFoo object goes out of scope it automatically calls my .NET object's dispose code.  I would think I could do it by overriding the Release(), and if the object count = 0 then call MyDispose().  But apparently I'm not overriding Release() correctly because my Release() method is never called.

Obviously, I can make this happen by putting my MyDispose() method in the interface and requiring the people using my object to call MyDispose() before Release(), but it would be slicker if Release() just cleaned up the object.

Is it possible to force the .NET COM object's destructor, or some other method, to be called immediately when a COM object is released?

Googling on this issue gets me a lot of hits telling me to call System.Runtime.InteropServices.Marshal.ReleaseComObject(), but of course, that's how you tell .NET to release a COM object.  I want COM Release() to Dispose of a .NET object.

Body:
I have a COM object written in managed code (C++/CLI). I am using that object in standard C++.
  How do I force my COM object's destructor to be called immediately when the COM object is released? If that's not possible, can I have Release() call a Dispose() (not MyDispose() - GBG) method on my (managed DotNet - GBG) COM object?

RE:  Forcing a deterministic release of resources bound by a DotNet COM Server when the client is unmanaged code.  These resource can be arranged to be released when the Garbage Collector collects the item, but that is not deterministic and such resources as file streams may not be released for hours or days for large memory systems where garbage collection is infrequent.

This is a common problem with COM Callable Wrappers (CCW's) as can be seen by another somewhat related thread at:  Is it possible to intercept (or be aware of) COM Reference counting on CLR objects exposed to COM.  in that case as in any case where one is writing their own COM client, no matter whether under managed or unmanaged code, is easy to solve just by a call to the IDisposable.Dispose() method as was done there.  However, that method would not work for (say) a DotNet COM codec class whose client may be the operating system itself and which client shouldn't have to be aware that the COM server is unmanaged or managed (DotNet).

One can implement the IDisposable.Dispose() pattern on the DotNet COM server as per the MSDN link:  http://msdn.microsoft.com/en-us/library/system.idisposable.aspx, but that won't do any good because the Dispose() method will never get called by the CCW.  Ideally, the implementation of the CCW's in mscoree.dll should really check for and call the IDisposable.Dispose() method if implemented as part of the CCW release and/or finalization/destructor.  I'm not sure why Microsoft did not do this, as having full access to the Assembly information they could easily determine if the DotNet COM Class supports IDisposable and just call Dispose() on final release if it does, and since this would be within the CCW, all the complexities about handling reference counting due to the extra interface reference could be avoided.

I can't see how this would "break" any existing code, as any client that is IDisposable aware could still call Dispose(), which if implemented according to the above template only effectively does anything on the first call.  Microsoft may be worried about a class being Disposed while there are still managed references to it that wouldn't know about it being Disposed until there start to be exceptions thrown by trying to use already disposed resources, but that is a potential problem for any improper use of the IDisposable interface even with only DotNet clients:  if there are multiple references to the same object instance and any one of them calls Dispose(), the others will find trying to use the required disposed resources cause exceptions.  For such cases, one should always put in guards using the disposing boolean (as per the IDisposable pattern template) or only reference the object through a common wrapper.

Since Microsoft hasn't done the required few lines of code in the implementation of CCW's in mscoree.dll, I wrote a wrapper around mscoree.dll that adds this extra functionality.  It is a little bit complex in that in order to control the creation of my wrapper around any instance of any DotNet COM Class, I need to also wrap the IClassFactory interface and aggregate the CCW instance in my "CCW_Wrapper" wrapper class.  This wrapper also supports further levels of aggregation from yet another outer class.  The code also does reference counting on instances of classes within the mscoree.dll implementation in use so as to be able to call FreeLibrary on mscoree.dll when there are no references (and LoadLibrary again if necessary later).  The code should also be multi threading friendly as is required for COM under Windows 7.  My C++ code is as follows:

EDITED 22 December 2010:  Eliminated one unnecessary parameter of COM_Wrapper constructor:

#include <windows.h>

HMODULE g_WrappedDLLInstance = NULL;
ULONG g_ObjectInstanceRefCnt = 0;

//the following is the C++ definition of the IDisposable interface
//using the GUID as per the managed definition, which never changes across
//DotNet versions as it represents a hash of the definition and its
//namespace, none of which can change by definition.
MIDL_INTERFACE("805D7A98-D4AF-3F0F-967F-E5CF45312D2C")
    IDisposable : public IDispatch {
    public:
        virtual VOID STDMETHODCALLTYPE Dispose() = 0;
    };

class CCW_Wrapper : public IUnknown {
public:
    // constructor and destructor
    CCW_Wrapper(
        __in IClassFactory *pClassFactory,
        __in IUnknown *pUnkOuter) :
            iWrappedIUnknown(nullptr),
            iOuterIUnknown(pUnkOuter),
            iWrappedIDisposable(nullptr),
            ready(FALSE),
            refcnt(0) {
        InterlockedIncrement(&g_ObjectInstanceRefCnt);
        if (!this->iOuterIUnknown)
            this->iOuterIUnknown = static_cast<IUnknown*>(this);
        pClassFactory->CreateInstance(
            this->iOuterIUnknown,
            IID_IUnknown,
            (LPVOID*)&this->iWrappedIUnknown);
        if (this->iWrappedIUnknown) {
            if (SUCCEEDED(this->iWrappedIUnknown->QueryInterface(__uuidof(IDisposable), (LPVOID*)&this->iWrappedIDisposable)))
                this->iOuterIUnknown->Release(); //to clear the reference count caused by the above.
        }
        this->ready = TRUE; //enable destruction of the object when release decrements to zero.
        //OUTER IUNKNOWN OBJECTS MUST ALSO PROTECT THEIR DESTRUCTORS IN SIMILAR MANNERS!!!!!
    }
    ~CCW_Wrapper() {
        this->ready = FALSE; //protect from re-entering this destructor when object released to zero.
        if (this->iWrappedIDisposable) {
            //the whole reason for this project!!!!!!!!
            this->iWrappedIDisposable->Dispose();
            //the following may be redundant, but to be sure...
            this->iOuterIUnknown->AddRef();
            this->iWrappedIDisposable->Release();
        }
        if (this->iWrappedIUnknown)
            this->iWrappedIUnknown->Release();
        if (!InterlockedDecrement(&g_ObjectInstanceRefCnt)) {
            //clear all global resources including the mutex, multithreading safe...
            HMODULE m = (HMODULE)InterlockedExchangePointer((PVOID*)&g_WrappedDLLInstance, (LPVOID)0);
            if (m)
                FreeLibrary(m);
        }
    }

    // IUnknown Interface
    STDMETHOD(QueryInterface)(REFIID riid, void **ppv) {
        if (ppv) {
            *ppv = nullptr;
            if (riid == IID_IUnknown) {
                *ppv = static_cast<IUnknown*>(this);
                this->AddRef();
                return S_OK;
            }
            else if (this->iWrappedIUnknown) {
                return this->iWrappedIUnknown->QueryInterface(riid, ppv);
            }
            return E_NOINTERFACE;
        }
        return E_INVALIDARG;
    }

    STDMETHOD_(ULONG, AddRef)() {
        return InterlockedIncrement(&this->refcnt);
    }

    STDMETHOD_(ULONG, Release)() {
        if (InterlockedDecrement(&this->refcnt))
            return this->refcnt;
        if (this->ready) //if not being constructed or destructed...
            delete this;
        return 0;
    }

private:
    IUnknown *iOuterIUnknown;
    IUnknown *iWrappedIUnknown;
    IDisposable *iWrappedIDisposable;
    BOOL ready;
    ULONG refcnt;
};

class ClassFactoryWrapper : public IClassFactory {
public:
    // constructor and destructor
    ClassFactoryWrapper(IClassFactory *icf) : wrappedFactory(icf), refcnt(0), lockcnt(0) {
        InterlockedIncrement(&g_ObjectInstanceRefCnt);
    }
    ~ClassFactoryWrapper() {
        if (wrappedFactory)
            wrappedFactory->Release();
        if (!InterlockedDecrement(&g_ObjectInstanceRefCnt)) {
            //clear all global resources, multithreading safe...
            HMODULE m = (HMODULE)InterlockedExchangePointer((PVOID*)&g_WrappedDLLInstance, (LPVOID)0);
            if (m)
                FreeLibrary(m);
        }
    }

    // IUnknown Interface
    STDMETHOD(QueryInterface)(REFIID riid, void **ppv) {
        if (ppv) {
            *ppv = nullptr;
            if (riid == IID_IUnknown) {
                *ppv = static_cast<IUnknown*>(this);
                this->AddRef();
            }
            else if (riid == IID_IClassFactory) {
                *ppv = static_cast<IClassFactory*>(this);
                this->AddRef();
            }
            else {
                return E_NOINTERFACE;
            }
            return S_OK;
        }
        return E_INVALIDARG;
    }

    STDMETHOD_(ULONG, AddRef)() {
        return InterlockedIncrement(&this->refcnt);
    }

    STDMETHOD_(ULONG, Release)() {
        if (InterlockedDecrement(&this->refcnt) || this->lockcnt)
            return this->refcnt;
        delete this;
        return 0;
    }

    // IClassFactory Interface
    STDMETHOD(CreateInstance)(IUnknown *pUnkOuter, REFIID riid, void **ppv) {
        HRESULT result = E_INVALIDARG;

        if (ppv) {
            *ppv = nullptr;
            if (pUnkOuter && (riid != IID_IUnknown))
                return result;
            CCW_Wrapper *oipm = new CCW_Wrapper(wrappedFactory, pUnkOuter);
            if (!oipm)
                return E_OUTOFMEMORY;
            if (FAILED(result = oipm->QueryInterface(riid, ppv)))
                delete oipm;
        }

        return result;
    }

    STDMETHOD(LockServer)(BOOL fLock) {
        if (fLock)
            InterlockedIncrement(&this->lockcnt);
        else {
            if (!InterlockedDecrement(&this->lockcnt) && !this->refcnt)
                delete this;
        }
        return wrappedFactory->LockServer(fLock);
    }

private:
    IClassFactory *wrappedFactory;
    ULONG refcnt;
    ULONG lockcnt;
};

STDAPI DllGetClassObject(__in REFCLSID rclsid, __in REFIID riid, __deref_out LPVOID FAR* ppv) {
    HRESULT result = E_INVALIDARG;

    if (ppv) {
        *ppv = nullptr;
        if ((riid != IID_IUnknown) && (riid != IID_IClassFactory))
            return E_NOINTERFACE;
        HMODULE hDLL = LoadLibrary(L"mscoree.dll");
        if (!hDLL)
            return E_UNEXPECTED;
        typedef HRESULT (__stdcall *pDllGetClassObject) (__in REFCLSID, __in REFIID, __out LPVOID *);
        pDllGetClassObject DllGetClassObject = (pDllGetClassObject)GetProcAddress(hDLL, "DllGetClassObject");
        if (!DllGetClassObject) {
            FreeLibrary(hDLL);
            return E_UNEXPECTED;
        }
        IClassFactory *icf = nullptr;
        if (FAILED(result = (DllGetClassObject)(rclsid, IID_IClassFactory, (LPVOID*)&icf))) {
            FreeLibrary(hDLL);
            return result;
        }
        ClassFactoryWrapper *cfw = new ClassFactoryWrapper(icf);
        if (!cfw) {
            icf->Release();
            FreeLibrary(hDLL);
            return E_OUTOFMEMORY;
        }
        //record the HMODULE instance in global variable for freeing later, multithreaded safe...
        hDLL = (HMODULE)InterlockedExchangePointer((PVOID*)&g_WrappedDLLInstance, (LPVOID)hDLL);
        if (hDLL)
            FreeLibrary(hDLL);
        if (FAILED(result = cfw->QueryInterface(IID_IClassFactory, ppv)))
            delete cfw; //will automatically free library and the held class factory reference if necessary.
    }
    return result;
}

extern "C"
HRESULT __stdcall DllCanUnloadNow(void) {
    if (g_ObjectInstanceRefCnt)
        return S_FALSE;
    return S_OK;
}

extern "C"
BOOL APIENTRY DllMain( HMODULE hModule,
                                                DWORD  ul_reason_for_call,
                                                LPVOID lpReserved ) {
    switch (ul_reason_for_call) {
        case DLL_PROCESS_ATTACH:
        case DLL_THREAD_ATTACH:
        case DLL_THREAD_DETACH:
        case DLL_PROCESS_DETACH:
            break;
    }
    return TRUE;
}

A '.def' file is also required for the DLL as follows:

LIBRARY mscoreeCOM_DisposeWrapper

EXPORTS
    DllCanUnloadNow         PRIVATE
    DllGetClassObject       PRIVATE

To use this source code, compile it into a DLL and install the DLL into the Windows SYSTEM folder, then have your installation program or your [COMRegisterFunction] method in your DotNet COM server modify the class registry entry for the InprocServer32 from mscoree.dll to the name of this wrapper (say mscoreeWrapper.dll).  It can be compiled under 32 and/or 64 bit, and for installation on 64-bit systems should have the 64-bit version put into the System folder and the 32-bit version put into the SysWOW64 folder; also, both the normal CLSID registration and the virtualized WOW6432 versions should be modified as to the InprocServer32 entries.  Some applications may require this wrapper DLL to be digitally signed to work seamlessly, which is a whole other subject.  If someone wants, I'll make a link to my compiled versions of these DLL's available here.

As I said, the required few lines (excluding the wrapper requirements) technique should really be incorporated into mscoree.dll.  Does anyone know how to contact someone within the appropriate department within Microsoft to make this suggestion?

EDITADD:  I have submitted a suggestion for the DotNet Framework to Microsoft Connect. This seems to be the best way of giving Microsoft feedback.

EDITADD2:  In implementing a workaround for this problem, I realized why MIcrosoft likely will not implement this "Auto calling of Dispose, if supported, when the CCW reference count drops to zero". In writing the workaround, I had to obtain a reference pointer to a COM interface on a managed object in order to pass it to a pure unmanaged COM method, and then had to Release() that reference count in order to not have the CCW strongly referencing the object and therefore causing a memory leak by never having it available for garbage collection. I did this because I know that decreasing a reference count to zero on a managed object currently only makes the CCW drop its strong reference to the object, making it eligible for garbage collection if there are no other references. However, if Microsoft implemented the Auto Dispose fix as I have suggested or if this code was in place wrapping the mscoree.dll functionality, this would trigger a Dispose() on the managed object when it wasn't wanted. For this particular case, I could "guard" the Dispose(bool disposing) virtual method to prevent the Dispose() happening, but for any existing code that uses this behaviour with the same assumption, including Microsoft's implementation of the DotNet Runtime Libraries, implementing this "fix" on the CCW would break that existing code.  This wrapper fix still applies for COM Servers one writes themselves and is aware of this side effect, as they can put the "guards" in place on the Dispose().

EDITADD 3:  In further work with this, I see that my suggestion to Microsoft is still valid and the problems of "breaking" existing code can be avoided by the fix that would call the IDisposable.Dispose() method on the object instance implementing the managed COM server if the interface exists only if a new custom attribute such as [AutoComDispose(true)], whose default value is false, is applied to the managed COM server class.  In this way, the programmer would choose to implement the functionality and the documentation on the new attribute would caution its use regarding having to "guard" the Dispose() method such as with a "artificial reference count" when there is a possibility of the Marshal.Release() method being called explicitly by in code used by the managed server or implicitly by calls to methods such as Marshal.GetObjectForIUnknown(), which in some cases can call QueryInterface and Release of the reference point if the ComObject is a managed object.

The main problem with this Answer is the complexity of installing it for use, as noted above.


来源: stackexchange

问:
Angular 2 Root module merge
I created a multi App application with several root ngModule's that works perfectly as separate apps.
I'm using Angular 4 with ng-cli.
Now I want to achieve the same but i'm thiking in a way to merge the root ngModules of each app into one to launch all the separated apps integrated.

Any clues on how to achieve this?

答:
Say you have modules: A, B, and C.  Now you would probably want to make a new module called AppModule which then imports A, B, and C like so:

```<code>  @NgModule({
  ... (all the other stuff that normally goes into ng module)
  imports: [
    A,
    B,
    C
  ] }
</code>```

You will now need to figure out your routing structure.  You said that you had multiple stand alone applications.  In that scenario they might have all live on different domains but if you combine them into one mega application then you'll be better off to have them live from the same domain.

So you'll need a url structure like app.com/A, app.com/B, and app.com/C for the different apps.

ContentLicense: CC BY-SA 3.0

Title: Angular 2 Root module merge

Body:
Say you have modules: A, B, and C.  Now you would probably want to make a new module called AppModule which then imports A, B, and C like so:

  @NgModule({
  ... (all the other stuff that normally goes into ng module)
  imports: [
    A,
    B,
    C
  ] }

You will now need to figure out your routing structure.  You said that you had multiple stand alone applications.  In that scenario they might have all live on different domains but if you combine them into one mega application then you'll be better off to have them live from the same domain.

So you'll need a url structure like app.com/A, app.com/B, and app.com/C for the different apps.


问:
How to make so that the toolbar does not overlap?
I am trying to add a list in the main main, but the toolbar is overridden making in the execution the first element is not seen.

Any solution

The main layout

```<code>    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/AppTheme.AppBarOverlay">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="@android:color/holo_red_dark"
            app:popupTheme="@style/AppTheme.PopupOverlay" />

    </android.support.design.widget.AppBarLayout>

    <include layout="@layout/list_elec" />

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|end"
        android:layout_margin="@dimen/fab_margin"
    app:backgroundTint="@android:color/holo_red_dark"
    app:srcCompat="@android:drawable/ic_input_add" />

</android.support.design.widget.CoordinatorLayout>
</code>```

The theme used in the application

```<code>  <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>

    <style name="AppTheme.NoActionBar">
        <item name="windowActionBar">false</item>
        <item name="windowNoTitle">true</item>
    </style>

    <style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />

    <style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />
</code>```

The manifest of the application

```<code> <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name"
            android:theme="@style/AppTheme.NoActionBar">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</code>```

答:
Maybe you should add :

```<code>android:fitsSystemWindows="true"
</code>```

to CoordinatorLayout and AppBarLayout

Body:
I am trying to add a list in the main main, but the toolbar is overridden making in the execution the first element is not seen.

Any solution

The main layout

    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/AppTheme.AppBarOverlay">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="@android:color/holo_red_dark"
            app:popupTheme="@style/AppTheme.PopupOverlay" />

    </android.support.design.widget.AppBarLayout>

    <include layout="@layout/list_elec" />

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|end"
        android:layout_margin="@dimen/fab_margin"
    app:backgroundTint="@android:color/holo_red_dark"
    app:srcCompat="@android:drawable/ic_input_add" />

</android.support.design.widget.CoordinatorLayout>

The theme used in the application

Body:
Maybe you should add :

android:fitsSystemWindows="true"

to CoordinatorLayout and AppBarLayout


问:
BlackBerry in-app purchase similar to iPhone
I want to implement in-app purchasing similar to what is available on the iPhone.
After searching, I learned that RIM will be releasing a BlackBerry Payment Service,
but I can't get any details about this.

Does anyone have details about how to implement in-app purchases on BlackBerry?

答: RIM has a set of pages about Application Platform Services, one of which is the Payment Service, which includes a link to download the sdk. I haven't tried this personally.</p>

ContentLicense: CC BY-SA 2.5


问:
Replicate Instagram Search-Style Swiping Tabs
I'm trying out some new things in swift. However, i'm fairly inexperienced so please bear with me if I use wrong terminology.

I'm looking to replicate Instagram's search view, as shown here:

the animation to the next table is shown here:

http://i.imgur.com/XUxG31w.jpg

I'd appreciate any help y'all can offer on how to replicate this. Thanks.

答:
This is a custom view that is not available by default in UIKit. However, it can be built by creating your own custom views.

You can use a UIScrollView with isPagingEnabled set to true. To implement the other features, you can use the scrollViewDidScroll method on UIScrollViewDelegate and the setContentOffset method to manipulate the scroll position in code.

Alternatively, there are some libraries on GitHub (example: XLPagerTabStrip Library) which you can include in your app. The source code is available so you can see how they implemented their views to build your own.

ContentLicense: CC BY-SA 4.0


问:
Importing JSON into Pandas
I have to following JSON that is coming from an API (e.g. my_json). The array of entities is stored in a key called entities:

```<code>{
    "action" : "get",
    "application" : "4d97323f-ac0f-11e6-b1d4-0eec2415f3df",
    "params" : {
      "limit" : [ "2" ]
    },
    "path" : "/businesses",
    "entities" : [
        {
            "uuid" : "508d56f1-636b-11e7-9928-122e0737977d",
            "type" : "business",
            "size" : 730 },
        {
            "uuid" : "2f3bd4dc-636b-11e7-b937-0ad881f403bf",
            "type" : "business",
            "size" : 730
        } ],
  "timestamp" : 1499469891059,
  "duration" : 244,
  "count" : 2
}
</code>```

I am trying to load them into a data frame as follows:

```<code>import pandas as pd

pd.read_json(my_json['entities'], orient='split')
</code>```

I get the following error:

```<code>ValueError: Invalid file path or buffer object type: <type 'list'>
</code>```

I have tried records orientation and still doesn't work.

答:
danielcorin pointed me in the right direction. I ended up having to do:

```<code>pd.read_json(json.dumps(b_j['entities']) , orient='list')
</code>```

The read_json method takes a string so I dump the entities collection and use that.

Title: Importing JSON into Pandas

Body:
I have to following JSON that is coming from an API (e.g. my_json). The array of entities is stored in a key called entities:

{
    "action" : "get",
    "application" : "4d97323f-ac0f-11e6-b1d4-0eec2415f3df",
    "params" : {
      "limit" : [ "2" ]
    },
    "path" : "/businesses",
    "entities" : [
        {
            "uuid" : "508d56f1-636b-11e7-9928-122e0737977d",
            "type" : "business",
            "size" : 730 },
        {
            "uuid" : "2f3bd4dc-636b-11e7-b937-0ad881f403bf",
            "type" : "business",
            "size" : 730
        } ],
  "timestamp" : 1499469891059,
  "duration" : 244,
  "count" : 2
}

I am trying to load them into a data frame as follows:

import pandas as pd

pd.read_json(my_json['entities'], orient='split')

I get the following error:

ValueError: Invalid file path or buffer object type: <type 'list'>

I have tried records orientation and still doesn't work.

Body:
danielcorin pointed me in the right direction. I ended up having to do:

pd.read_json(json.dumps(b_j['entities']) , orient='list')

The read_json method takes a string so I dump the entities collection and use that.


问:
Ajax Tooltip - bypass so not to use bootstrap
I found this code on stackoverflow.com and I would like to ask how do I do the same but without using bootstrap, I would only like to use jquery (if needed) ?

The code below works great but I would like to know how would I do this without using bootstrap.

Thanks for any help.

CODE:

```<code><script type="text/javascript" src="//code.jquery.com/jquery-compat-git.js"></script>
<script type="text/javascript" src="//netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"></script>
<link rel="stylesheet" type="text/css" href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css">

<script type='text/javascript'>
//<![CDATA[
$(window).on('load', function() {
     // On first hover event we will make popover and then AJAX content into it.
    $('[data-poload]').hover(
        function (event) {
            var el = $(this);

            // disable this event after first binding
            el.off(event);

            // add initial popovers with LOADING text
            el.popover({
                content: "loading…", // maybe some loading animation like <img src='loading.gif />
                html: true,
                placement: "auto",
                container: 'body',
                trigger: 'hover'
            });

            // show this LOADING popover
            el.popover('show');

            // requesting data from unsing url from data-poload attribute
            $.get(el.data('poload'), function (d) {
                // set new content to popover
                el.data('bs.popover').options.content = d;

                // reshow popover with new content
                el.popover('show');
            });
        },
        // Without this handler popover flashes on first mouseout
        function() { }
    );
});//]]>

</script>

<img src="alerts.gif" data-poload="test3.php?id=1"><BR><BR><BR>
<img src="alerts.gif" data-poload="test3.php?id=2"><BR><BR><BR>
<img src="alerts.gif" data-poload="test3.php?id=3"><BR><BR><BR>
</code>```

答:
Check this:

// On first hover event we will make popover and then AJAX content into it.

$('[data-poload]').hover(function(event) {
  var el = $(this);
  // Commenting this (For testing purposes)
  $.get(el.data('poload'), function(d) {
    // set new content
    el.find('.tooltiptext').text(d);
  });
});```
<pre class="snippet-code-css lang-css prettyprint-override"><code>.tooltip {
    position: relative;
    display: table;
}

.tooltip .tooltiptext {
    visibility: hidden;
    width: 120px;
    background-color: black;
    color: #fff;
    border-radius: 6px;
    padding: 5px 10px;

    /* Position the tooltip */
    position: absolute;
    z-index: 1;
}

.tooltip:hover .tooltiptext {
    visibility: visible;
}

.tooltip .tooltiptext {
    top: -5px;
    left: 105%;
}</code>```

  Loading...

  Loading...

```

Body:
I found this code on stackoverflow.com and I would like to ask how do I do the same but without using bootstrap, I would only like to use jquery (if needed) ?

The code below works great but I would like to know how would I do this without using bootstrap.

Thanks for any help.

CODE:

<link rel="stylesheet" type="text/css" href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css">

Body:
Check this:

// On first hover event we will make popover and then AJAX content into it.

$('[data-poload]').hover(function(event) {
  var el = $(this);
  // Commenting this (For testing purposes)
  $.get(el.data('poload'), function(d) {
    // set new content
    el.find('.tooltiptext').text(d);
  });
});

.tooltip {
    position: relative;
    display: table;
}

.tooltip .tooltiptext {
    visibility: hidden;
    width: 120px;
    background-color: black;
    color: #fff;
    border-radius: 6px;
    padding: 5px 10px;

    /* Position the tooltip */
    position: absolute;
    z-index: 1;
}

.tooltip:hover .tooltiptext {
    visibility: visible;
}

.tooltip .tooltiptext {
    top: -5px;
    left: 105%;
}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="tooltip" data-poload="//demo2307137.mockable.io/test">
   <img src="alerts.gif"/>
   <br/><br/><br/>
  <span class="tooltiptext">Loading...</span>
</div>

<div class="tooltip" data-poload="//demo2307137.mockable.io/test">
   <img src="alerts.gif"/>
   <br/><br/><br/>
  <span class="tooltiptext">Loading...</span>
</div>


问:
How to loop through columns and retrieve column values?
I have a question regarding Oracle cursor.

I need to compare the values in a selected list of columns, see which records have changed after update. The table is huge, the only way to distinguish between new and old record is by the Batch_ID.

The output table will include these information:

enter image description here

So i have something very basic like below, except that i need to  write like hundreds of SELECT statement in order to go through hundreds of columns.

```<code>SELECT a.*, b.LAST_name AS last_name_updated --- here the variable could be ethnicity, income category etc..
from (SELECT person_id, last_name
      FROM   person
      WHERE batch_id = (select max(batch_id) from person)
     ) a FULL OUTER JOIN
     (SELECT person_id, last_name
      FROM   person
      WHERE batch_id = (select max(batch_id) - 1 from person)
     ) b
     ON a.person_id = b.person_id
WHERE  nvl(a.last_name,0) <> nvl(b.last_nm,0)
</code>```

I need to go through a list of about 500 field name like Income, Race, Last_Name etc and capture all the changes, if any, in all these columns.

how do i go about this without writing hundreds of these SELECT statements?

Thanks in advance for your help!

答:
This is a generic SQL statement that will use ALL_TAB_COLS to generate a SQL statement that can be used to compare columns:

```<code>  SELECT    CASE WHEN column_id = '1' THEN q'[ select 'batchid: ' || batchid ]' END
         || CASE
                WHEN column_name <> 'BATCHID'
                THEN
                       q'[ || case when ]'
                    || column_name
                    || q'[<> lag(]'
                    || column_name
                    || q'[) over (partition by batchid order by col1, col2) then ' ]'
                    || column_name
                    || ' has changed'' end'
            END
         || CASE WHEN column_id = MAX (column_id) OVER () THEN q'[ as changemessage from testtable]' END
             sql
    FROM all_tab_cols a
   WHERE table_name = 'TESTTABLE'
ORDER BY column_id;
</code>```

Test Case:

```<code>CREATE TABLE testtable
(
    batchid   INTEGER
  , col1      INTEGER
  , col2      INTEGER
);

BEGIN
    FOR batchid IN 1 .. 3
    LOOP
        FOR col1 IN 1 .. 3
        LOOP
            FOR col2 IN 1 .. 2
            LOOP
                INSERT INTO testtable
                     VALUES (batchid, col1, col2);
            END LOOP;
        END LOOP;
    END LOOP;
END;
</code>```

Execute the SQL and you generate the following SQL statement:

```<code>select 'batchid: ' || batchid
     || case when COL1<> lag(COL1) over (partition by batchid order by col1, col2) then ' COL1 has changed' end
     || case when COL2<> lag(COL2) over (partition by batchid order by col1, col2) then ' COL2 has changed' end as changemessage from testtable
</code>```

I will leave it to you to reduce the result set:

```<code>CHANGEMESSAGE
batchid: 1
batchid: 1
batchid: 1
batchid: 1
batchid: 1 COL2 has changed
batchid: 1
batchid: 1
batchid: 1
batchid: 1 COL1 has changed COL2 has changed
batchid: 1
batchid: 1
batchid: 1
batchid: 1 COL2 has changed
batchid: 1
batchid: 1
batchid: 1
batchid: 1 COL1 has changed COL2 has changed
batchid: 1
batchid: 1
batchid: 1
batchid: 1 COL2 has changed
batchid: 1
batchid: 1
batchid: 1
batchid: 2
batchid: 2
batchid: 2
batchid: 2
batchid: 2 COL2 has changed
batchid: 2
batchid: 2
batchid: 2
batchid: 2 COL1 has changed COL2 has changed
batchid: 2
batchid: 2
batchid: 2
batchid: 2 COL2 has changed
batchid: 2
batchid: 2
batchid: 2
batchid: 2 COL1 has changed COL2 has changed
batchid: 2
batchid: 2
batchid: 2
batchid: 2 COL2 has changed
batchid: 2
batchid: 2
batchid: 2
batchid: 3
batchid: 3
batchid: 3
batchid: 3
batchid: 3 COL2 has changed
batchid: 3
batchid: 3
batchid: 3
batchid: 3 COL1 has changed COL2 has changed
batchid: 3
batchid: 3
batchid: 3
batchid: 3 COL2 has changed
batchid: 3
batchid: 3
batchid: 3
batchid: 3 COL1 has changed COL2 has changed
batchid: 3
batchid: 3
batchid: 3
batchid: 3 COL2 has changed
batchid: 3
batchid: 3
batchid: 3
</code>```

Body:
I have a question regarding Oracle cursor.

I need to compare the values in a selected list of columns, see which records have changed after update. The table is huge, the only way to distinguish between new and old record is by the Batch_ID.

The output table will include these information:

enter image description here

So i have something very basic like below, except that i need to  write like hundreds of SELECT statement in order to go through hundreds of columns.

SELECT a.*, b.LAST_name AS last_name_updated --- here the variable could be ethnicity, income category etc..
from (SELECT person_id, last_name
      FROM   person
      WHERE batch_id = (select max(batch_id) from person)
     ) a FULL OUTER JOIN
     (SELECT person_id, last_name
      FROM   person
      WHERE batch_id = (select max(batch_id) - 1 from person)
     ) b
     ON a.person_id = b.person_id
WHERE  nvl(a.last_name,0) <> nvl(b.last_nm,0)

I need to go through a list of about 500 field name like Income, Race, Last_Name etc and capture all the changes, if any, in all these columns.

how do i go about this without writing hundreds of these SELECT statements?

Thanks in advance for your help!

Body:
This is a generic SQL statement that will use ALL_TAB_COLS to generate a SQL statement that can be used to compare columns:

  SELECT    CASE WHEN column_id = '1' THEN q'[ select 'batchid: ' || batchid ]' END
         || CASE
                WHEN column_name <> 'BATCHID'
                THEN
                       q'[ || case when ]'
                    || column_name
                    || q'[<> lag(]'
                    || column_name
                    || q'[) over (partition by batchid order by col1, col2) then ' ]'
                    || column_name
                    || ' has changed'' end'
            END
         || CASE WHEN column_id = MAX (column_id) OVER () THEN q'[ as changemessage from testtable]' END
             sql
    FROM all_tab_cols a
   WHERE table_name = 'TESTTABLE'
ORDER BY column_id;

Test Case:

CREATE TABLE testtable
(
    batchid   INTEGER
  , col1      INTEGER
  , col2      INTEGER
);

BEGIN
    FOR batchid IN 1 .. 3
    LOOP
        FOR col1 IN 1 .. 3
        LOOP
            FOR col2 IN 1 .. 2
            LOOP
                INSERT INTO testtable
                     VALUES (batchid, col1, col2);
            END LOOP;
        END LOOP;
    END LOOP;
END;

Execute the SQL and you generate the following SQL statement:

select 'batchid: ' || batchid
     || case when COL1<> lag(COL1) over (partition by batchid order by col1, col2) then ' COL1 has changed' end
     || case when COL2<> lag(COL2) over (partition by batchid order by col1, col2) then ' COL2 has changed' end as changemessage from testtable

I will leave it to you to reduce the result set:

CHANGEMESSAGE
batchid: 1
batchid: 1
batchid: 1
batchid: 1
batchid: 1 COL2 has changed
batchid: 1
batchid: 1
batchid: 1
batchid: 1 COL1 has changed COL2 has changed
batchid: 1
batchid: 1
batchid: 1
batchid: 1 COL2 has changed
batchid: 1
batchid: 1
batchid: 1
batchid: 1 COL1 has changed COL2 has changed
batchid: 1
batchid: 1
batchid: 1
batchid: 1 COL2 has changed
batchid: 1
batchid: 1
batchid: 1
batchid: 2
batchid: 2
batchid: 2
batchid: 2
batchid: 2 COL2 has changed
batchid: 2
batchid: 2
batchid: 2
batchid: 2 COL1 has changed COL2 has changed
batchid: 2
batchid: 2
batchid: 2
batchid: 2 COL2 has changed
batchid: 2
batchid: 2
batchid: 2
batchid: 2 COL1 has changed COL2 has changed
batchid: 2
batchid: 2
batchid: 2
batchid: 2 COL2 has changed
batchid: 2
batchid: 2
batchid: 2
batchid: 3
batchid: 3
batchid: 3
batchid: 3
batchid: 3 COL2 has changed
batchid: 3
batchid: 3
batchid: 3
batchid: 3 COL1 has changed COL2 has changed
batchid: 3
batchid: 3
batchid: 3
batchid: 3 COL2 has changed
batchid: 3
batchid: 3
batchid: 3
batchid: 3 COL1 has changed COL2 has changed
batchid: 3
batchid: 3
batchid: 3
batchid: 3 COL2 has changed
batchid: 3
batchid: 3
batchid: 3


问:
How does delegation work in array OrderBy method in C#?
I'm learning delegation with array data structure in C#. Please take a look at my code. I tried to expand lambda expression and delegation in array OrderBy() method in order to fully understand how it works. But Visual Studio gives syntax error even though the running result is correct. I'd appreciate it if someone can help me correct "delegation 3" part. Thank you.</p>

```<code>using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Test2 {
    class Program {

        delegate int Del(int i);

        static void Main(string[] args) {

            int[] MyArray = new int[5] { 3, 2, 6, 10, -3 };

            // print original array
            foreach (var i in MyArray) {
                Console.Write(i + " ");
            }

            Console.WriteLine();
            //Console.ReadKey();

            // sort array by using either Linq or OrderBy
            // Linq works
            //int[] mynewarray = (from i in MyArray orderby i ascending select i).ToArray();

            // delegation 1 works
            //int[] mynewarray = MyArray.OrderBy(i => i).ToArray();
            // delegation 2 works
            //int[] mynewarray = MyArray.OrderBy(delegate (int i) { return i; }).ToArray();
            // delegation 3 has syntax error
            Del del = MyInt;
            int[] mynewarray = MyArray.OrderBy(del(int i)).ToArray();

            // print sorted array
            foreach (var i in mynewarray) {
                Console.Write(i + " ");
            }

            Console.ReadKey();

        }
        public static int MyInt(int i) {
            return i;
        }

    }
}
</code>```

答:
You need to specify an input identifier (i in this case) and use the "goes to" (=>) operator.

option 1:

```<code>int[] orderedArray = MyArray.OrderBy(i => del(i)).ToArray();
</code>```

option 2:

```<code>int[] orderedArray = MyArray.OrderBy((int i) => del(i)).ToArray();
</code>```

Body:
I'm learning delegation with array data structure in C#. Please take a look at my code. I tried to expand lambda expression and delegation in array OrderBy() method in order to fully understand how it works. But Visual Studio gives syntax error even though the running result is correct. I'd appreciate it if someone can help me correct "delegation 3" part. Thank you.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Test2 {
    class Program {

        delegate int Del(int i);

        static void Main(string[] args) {

            int[] MyArray = new int[5] { 3, 2, 6, 10, -3 };

            // print original array
            foreach (var i in MyArray) {
                Console.Write(i + " ");
            }

            Console.WriteLine();
            //Console.ReadKey();

            // sort array by using either Linq or OrderBy
            // Linq works
            //int[] mynewarray = (from i in MyArray orderby i ascending select i).ToArray();

            // delegation 1 works
            //int[] mynewarray = MyArray.OrderBy(i => i).ToArray();
            // delegation 2 works
            //int[] mynewarray = MyArray.OrderBy(delegate (int i) { return i; }).ToArray();
            // delegation 3 has syntax error
            Del del = MyInt;
            int[] mynewarray = MyArray.OrderBy(del(int i)).ToArray();

            // print sorted array
            foreach (var i in mynewarray) {
                Console.Write(i + " ");
            }

            Console.ReadKey();

        }
        public static int MyInt(int i) {
            return i;
        }

    }
}

Body:
You need to specify an input identifier (i in this case) and use the "goes to" (=>) operator.

option 1:

int[] orderedArray = MyArray.OrderBy(i => del(i)).ToArray();

option 2:

int[] orderedArray = MyArray.OrderBy((int i) => del(i)).ToArray();


问:
Is there a diffForHumans() in Symfony
Is there a diffForHumans() function in symfony framework at like laravel.

```<code>$forumPost->created_at->diffForHumans();
</code>```

Thanks in advance

答:
you can use Carbon php extension and you can install it using composer:

Carbon php extension

and here is the link for diffForHumans()

Title: Is there a diffForHumans() in Symfony

Body:
Is there a diffForHumans() function in symfony framework at like laravel.

$forumPost->created_at->diffForHumans();

Thanks in advance


问:
mysql innodb buffer pool size which dependencies
I want to dimension RAM dependent on the innodb_buffer_pool_size. But all what I find is the dependence of the innodb_buffer_pool_size on RAM.

Can you tell me on which parameters on the innodb_buffer_pool_size depends? Number of queries? Number of transactions?

I want to find out the formula which calculates the RAM dependent on innodb_buffer_pool_size.

Can you help me? Thank you very much for your advice!

答:
Sizing innodb_buffer_pool_size:

If all the queries/transactions are touching tiny tables or tiny parts or big tables, then a tiny buffer_pool is sufficient.

If you have UUIDs, you need a big buffer pool -- because you can't touch only 'tiny' parts of the table/index via UUIDs; they are too 'random'.

Bigger than 70% of RAM is dangerous because it could lead to swapping, which is terrible for performance.

That's 70% of available RAM -- need to  leave room for the OS, code, other caches, etc.

When you change RAM, change the buffer_pool_size.  Or the other way around.

Bigger is better.

Much bigger than the total size of all data and indexes is unnecessary (wastes RAM).

Too small leads to inefficient operation of most operations involving InnoDB.

the buffer_pool is a cache.  Computer Science discusses what that means and what the ramifications are.

So, the simple formula "set it to 70% of available RAM".

There are various metrics in SHOW GLOBAL STATUS that can say whether the buffer_pool is "big enough".  But they are useful only after setting the size, then running for a while.  And they only say "there are lots of reads/writes", they don't say whether or by how much to change the size.

If you would like me to analyze the STATUS (after it has been up at least a day), provide

How much RAM

SHOW VARIABLES;

SHOW GLOBAL STATUS;

I will check those formulas, plus a couple hundred others.


问:
Exchange Strings with Numbers in R
I was just wondering if R has a way to convert a vector of strings into numbers which I define. For example, say we have a vector as follows:

```<code>vector <- c("ABC", "DEF", "GHI", "ABC", "GHI", "ABC")
</code>```

What I would like to do is rather than having the elements ABC, DEF, and GHI in the vector I would instead like to 'exchange' them with a user-defined number, such that rather than having ABC in the vector I have 1, instead of DEF I have 2, and instead of GHI I have 3, so the vector now becomes

```<code>vector <- c(1, 2, 3, 1, 3, 1)
</code>```

I know that there are functions which do something similar to this, but they don't quite do what I want. For instance, the function as.numeric(as.factor()) will convert a vector filled with string elements into numbers, which is what I want, but unfortunately it does not allow me to actually define what string value becomes what number, which would be a major problem when the dataset I'm using changes since the numbers would represent different strings.

Another alternative method is using the chartr(old = "ABC", new = "123", x) function (where x is your dataset) which is also good, but again the major problem behind it is the fact that the number of "old" characters must match the number of "new" characters but also the fact that every instance of a letter will be changed with a number, such that if we replace ABC with 123 then every time B occurs it will always be replaced with 2 which is not what I want.

Does R have a function which will allow me to swap strings in a vector with user-defined numbers?

EDIT: In particular (for anyone that wishes to do this in the future), I used the following function: levels(vector)[levels(vector)=="ABC"] <- "1" This allows you to swap individual string factor levels with a numerical value and vice versa

答:
```<code>vector <- c("ABC", "DEF", "GHI", "ABC", "GHI", "ABC")
vector
#[1] "ABC" "DEF" "GHI" "ABC" "GHI" "ABC"
vector=as.factor(vector)
vector
#[1] ABC DEF GHI ABC GHI ABC

vector=as.numeric(vector)
vector
#[1] 1 2 3 1 3 1
</code>```

Try it Online

Alternative solution:

Map Strings to user defined numbers

```<code>    #map strings to numbers
    numbers <- c(1,2,3)
    names <- c("ABC", "DEF", "GHI")

    #store maping in data frame
    df <- data.frame(names, numbers)
    df

     vector <-as.vector(  c("ABC", "DEF", "GHI", "ABC", "GHI", "ABC"))

     vector2=c() # the numeric vector
     for (i in 1:length(vector)){
     id <= which(df$names == vector[i])
     vector2 <= c(vector2 ,id)
     }
     print(vector2)
     #[1] 1 2 3 1 3 1
</code>```

Try it online

Title: Exchange Strings with Numbers in R

Body:
I was just wondering if R has a way to convert a vector of strings into numbers which I define. For example, say we have a vector as follows:

vector <- c("ABC", "DEF", "GHI", "ABC", "GHI", "ABC")

What I would like to do is rather than having the elements ABC, DEF, and GHI in the vector I would instead like to 'exchange' them with a user-defined number, such that rather than having ABC in the vector I have 1, instead of DEF I have 2, and instead of GHI I have 3, so the vector now becomes

vector <- c(1, 2, 3, 1, 3, 1)

I know that there are functions which do something similar to this, but they don't quite do what I want. For instance, the function as.numeric(as.factor()) will convert a vector filled with string elements into numbers, which is what I want, but unfortunately it does not allow me to actually define what string value becomes what number, which would be a major problem when the dataset I'm using changes since the numbers would represent different strings.

Another alternative method is using the chartr(old = "ABC", new = "123", x) function (where x is your dataset) which is also good, but again the major problem behind it is the fact that the number of "old" characters must match the number of "new" characters but also the fact that every instance of a letter will be changed with a number, such that if we replace ABC with 123 then every time B occurs it will always be replaced with 2 which is not what I want.

Does R have a function which will allow me to swap strings in a vector with user-defined numbers?

EDIT: In particular (for anyone that wishes to do this in the future), I used the following function: levels(vector)[levels(vector)=="ABC"] <- "1" This allows you to swap individual string factor levels with a numerical value and vice versa

Body:
vector <- c("ABC", "DEF", "GHI", "ABC", "GHI", "ABC")
vector
#[1] "ABC" "DEF" "GHI" "ABC" "GHI" "ABC"
vector=as.factor(vector)
vector
#[1] ABC DEF GHI ABC GHI ABC

vector=as.numeric(vector)
vector
#[1] 1 2 3 1 3 1

Try it Online

Alternative solution:

Map Strings to user defined numbers

    #map strings to numbers
    numbers <- c(1,2,3)
    names <- c("ABC", "DEF", "GHI")

    #store maping in data frame
    df <- data.frame(names, numbers)
    df

     vector <-as.vector(  c("ABC", "DEF", "GHI", "ABC", "GHI", "ABC"))

     vector2=c() # the numeric vector
     for (i in 1:length(vector)){
     id <= which(df$names == vector[i])
     vector2 <= c(vector2 ,id)
     }
     print(vector2)
     #[1] 1 2 3 1 3 1

Try it online


问:
Shrink double if statement in Python
I cannot use the following statement because x and y may be defined as None:

```<code>if x*y > 9:
    pass
</code>```

unsupported operand type(s) for *: 'NoneType' and 'NoneType'

So I should check first for the existence:

```<code>if x and y:
    if x*y > 9:
        pass
</code>```

It seems a bit redundant. Is there a better way to achieve this?

答:
You can do:

```<code>if x and y and x*y > 9:
    pass
</code>```

If you get even more checks it might be more comfortable to use all:

```<code>if all([
    x,
    y,
    x*y > 9,
    other conditions,...]):
    pass
</code>```

Title: Shrink double if statement in Python

Body:
I cannot use the following statement because x and y may be defined as None:

if x*y > 9:
    pass

unsupported operand type(s) for *: 'NoneType' and 'NoneType'

So I should check first for the existence:

if x and y:
    if x*y > 9:
        pass

It seems a bit redundant. Is there a better way to achieve this?

Body:
You can do:

if x and y and x*y > 9:
    pass

If you get even more checks it might be more comfortable to use all:

if all([
    x,
    y,
    x*y > 9,
    other conditions,...]):
    pass


问:
Spring Security hasPermission for Collection<Object>
I have working application secured with method-level security:

RestController:

```<code>@PreAuthorize("hasPermission(#product, 'WRITE')")
@RequestMapping(value = "/save", method = RequestMethod.POST)
public Product save(@RequestBody Product product) {
    return productService.save(product);
}
</code>```

PermissionEvaluator:

```<code>public class SecurityPermissionEvaluator implements PermissionEvaluator {

    private Logger log = LoggerFactory.getLogger(SecurityPermissionEvaluator.class);

    private final PermissionService permissionService;

    public SecurityPermissionEvaluator(PermissionService permissionService) {
        this.permissionService = permissionService;
    }

    @Override
    public boolean hasPermission(Authentication authentication, Object targetDomainObject, Object permission) {
        CustomUserDetails userDetails = (CustomUserDetails) authentication.getPrincipal();
        return permissionService.isAuthorized(userDetails.getUser(), targetDomainObject, permission.toString());
    }

    @Override
    public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, Object permission) {
        // almost the same implementation
    }
}
</code>```

And everything works fine until I implemented API which saves collection of objects. The logic of this service is to update existing entities and/or create new entities.

```<code>@PreAuthorize("hasPermission(#products, 'WRITE')")
@RequestMapping(value = "/saveCollection", method = RequestMethod.POST)
public Collection<Product> save(@RequestBody Collection<Product> products) {
    return productService.save(products);
}
</code>```

After this my permission service handles the collection object and looks like this now:

PemissionService:

```<code>public class PermissionService {

    public boolean isAuthorized(User user, Object targetDomainObject, String permission) {
        if (targetDomainObject instanceof TopAppEntity) {
            if (((TopAppEntity) targetDomainObject).getId() == null) {
                // check authorities and give response
            } else {
                // check ACL and give response
            }
        } else if(targetDomainObject instanceof Collection) {
            boolean isAuthorized = false;
            Collection targetDomainObjects = (Collection) targetDomainObject;
            for (Object targetObject : targetDomainObjects) {
                isAuthorized = isAuthorized(user, targetObject, permission);
                if (!isAuthorized) break;
            }
            return isAuthorized;
        }
    }
}
</code>```

My question is:

How I can handle collections using @PreAuthorize("hasPermission(#object, '...')") more elegant way? Is there some implementations in Spring Security for handling collections? At least, how can I optimize PemissionService for handling Collections?

答:
I have a couple of workarounds.

1. The first one is to use my own MethodSecurityExpressionHandler and MethodSecurityExpressionRoot.

Creating a CustomMethodSecurityExpressionRoot and define a method which will be our new expression for Collection handling. It will extend SecurityExpressionRoot to include default expressions:

```<code>public class CustomMethodSecurityExpressionRoot extends SecurityExpressionRoot implements MethodSecurityExpressionOperations {

    private final PermissionEvaluator permissionEvaluator;
    private final Authentication authentication;

    private Object filterObject;
    private Object returnObject;
    private Object target;

    public CustomMethodSecurityExpressionRoot(Authentication authentication, PermissionEvaluator permissionEvaluator) {
        super(authentication);
        this.authentication = authentication;
        this.permissionEvaluator = permissionEvaluator;
        super.setPermissionEvaluator(permissionEvaluator);
    }

    public boolean hasAccessToCollection(Collection<Object> collection, String permission) {
        for (Object object : collection) {
            if (!permissionEvaluator.hasPermission(authentication, object, permission))
                return false;
        }
        return true;
    }

    @Override
    public void setFilterObject(Object filterObject) {
        this.filterObject = filterObject;
    }

    @Override
    public Object getFilterObject() {
        return filterObject;
    }

    @Override
    public void setReturnObject(Object returnObject) {
        this.returnObject = returnObject;
    }

    @Override
    public Object getReturnObject() {
        return returnObject;
    }

    @Override
    public Object getThis() {
        return target;
    }
}
</code>```

Create custom expression handler and inject CustomMethodSecurityExpressionRoot:

```<code>public class CustomMethodSecurityExpressionHandler extends DefaultMethodSecurityExpressionHandler {

    private final PermissionEvaluator permissionEvaluator;

    public CustomMethodSecurityExpressionHandler(PermissionEvaluator permissionEvaluator) {
        this.permissionEvaluator = permissionEvaluator;
        super.setPermissionEvaluator(permissionEvaluator);
    }

    @Override
    protected MethodSecurityExpressionOperations createSecurityExpressionRoot(
            Authentication authentication, MethodInvocation invocation) {
        CustomMethodSecurityExpressionRoot root =
                new CustomMethodSecurityExpressionRoot(authentication, permissionEvaluator);
        root.setTrustResolver(new AuthenticationTrustResolverImpl());
        root.setRoleHierarchy(getRoleHierarchy());
        return root;
    }
}
</code>```

I also injected SecurityPermissionEvaluator used in question, so it will be a single point of entry for custom and default expressions. As an alternate option we could inject and use PermissionService directly.

Configuring our method-level security:

```<code>@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {

    @Autowired
    private PermissionService permissionService;

    @Override
    protected MethodSecurityExpressionHandler createExpressionHandler() {
        PermissionEvaluator permissionEvaluator = new SecurityPermissionEvaluator(permissionService);
        return new CustomMethodSecurityExpressionHandler(permissionEvaluator);
    }
}
</code>```

Now we can use new expression in RestController:

```<code>@PreAuthorize("hasAccessToCollection(#products, 'WRITE')")
@RequestMapping(value = "/saveCollection", method = RequestMethod.POST)
public Collection<Product> save(@RequestBody Collection<Product> products) {
    return productService.save(products);
}
</code>```

As a result a part with handling collection in PermissionService could be omitted as we took out this logic to custom expression.

2. The second workaround is to call method directly using SpEL.

Now I'm using PermissionEvaluator as Spring bean (any service could be used here, but I'm preferring single point of entry again)

```<code>@Component
public class SecurityPermissionEvaluator implements PermissionEvaluator {

    @Autowired
    private PermissionService permissionService;

    @Override
    public boolean hasPermission(Authentication authentication, Object targetDomainObject, Object permission) {
        if (!(targetDomainObject instanceof TopAppEntity))
            throw new IllegalArgumentException();
        CustomUserDetails userDetails = (CustomUserDetails) authentication.getPrincipal();
        return permissionService.isAuthorized(userDetails.getUser(), targetDomainObject, permission.toString());
    }

    @Override
    public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, Object permission) {
        CustomUserDetails userDetails = (CustomUserDetails) authentication.getPrincipal();
        try {
            return permissionService.isAuthorized(userDetails.getUser(), targetId,
                    Class.forName(targetType), String.valueOf(permission));
        } catch (ClassNotFoundException e) {
            throw new IllegalArgumentException("No class found " + targetType);
        }
    }

    public boolean hasPermission(Authentication authentication, Collection<Object> targetDomainObjects, Object permission) {
        for (Object targetDomainObject : targetDomainObjects) {
            if (!hasPermission(authentication, targetDomainObject, permission))
                return false;
        }
        return true;
    }

}
</code>```

Configuring method security:

```<code>@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {

    @Autowired
    private PermissionEvaluator permissionEvaluator;
    @Autowired
    private ApplicationContext applicationContext;

    @Override
    protected MethodSecurityExpressionHandler createExpressionHandler() {
        DefaultMethodSecurityExpressionHandler expressionHandler =
                new DefaultMethodSecurityExpressionHandler();
        expressionHandler.setPermissionEvaluator(permissionEvaluator);
        // Pay attention here, or Spring will not be able to resolve bean
        expressionHandler.setApplicationContext(applicationContext);
        return expressionHandler;
    }
}
</code>```

Usage of the service in expression:

```<code>@PreAuthorize("@securityPermissionEvaluator.hasPermission(authentication, #products, 'WRITE')")
@RequestMapping(value = "/saveCollection", method = RequestMethod.POST)
public Collection<Product> save(@RequestBody Collection<Product> products) {
    return productService.save(products);
}
</code>```

Spring beans created by default with class name if no other name specified.

Summary: both approaches based on using custom services calling them directly or registering them as expressions and could handle the logic of collection before it will be sent to authority checking service, so we can omit the part of it:

```<code>@Service
public class PermissionService {

    public boolean isAuthorized(User user, TopAppEntity domainEntity, String permission) {
        // removed instanceof checks and can operate on domainEntity directly
        if (domainEntity.getId() == null) {
            // check authorities and give response
        } else {
            // check ACL and give response
        }
    }
}
</code>```

Body:
I have working application secured with method-level security:

RestController:

@PreAuthorize("hasPermission(#product, 'WRITE')")
@RequestMapping(value = "/save", method = RequestMethod.POST)
public Product save(@RequestBody Product product) {
    return productService.save(product);
}

PermissionEvaluator:

public class SecurityPermissionEvaluator implements PermissionEvaluator {

    private Logger log = LoggerFactory.getLogger(SecurityPermissionEvaluator.class);

    private final PermissionService permissionService;

    public SecurityPermissionEvaluator(PermissionService permissionService) {
        this.permissionService = permissionService;
    }

    @Override
    public boolean hasPermission(Authentication authentication, Object targetDomainObject, Object permission) {
        CustomUserDetails userDetails = (CustomUserDetails) authentication.getPrincipal();
        return permissionService.isAuthorized(userDetails.getUser(), targetDomainObject, permission.toString());
    }

    @Override
    public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, Object permission) {
        // almost the same implementation
    }
}

And everything works fine until I implemented API which saves collection of objects. The logic of this service is to update existing entities and/or create new entities.

@PreAuthorize("hasPermission(#products, 'WRITE')")
@RequestMapping(value = "/saveCollection", method = RequestMethod.POST)
public Collection<Product> save(@RequestBody Collection<Product> products) {
    return productService.save(products);
}

After this my permission service handles the collection object and looks like this now:

PemissionService:

public class PermissionService {

    public boolean isAuthorized(User user, Object targetDomainObject, String permission) {
        if (targetDomainObject instanceof TopAppEntity) {
            if (((TopAppEntity) targetDomainObject).getId() == null) {
                // check authorities and give response
            } else {
                // check ACL and give response
            }
        } else if(targetDomainObject instanceof Collection) {
            boolean isAuthorized = false;
            Collection targetDomainObjects = (Collection) targetDomainObject;
            for (Object targetObject : targetDomainObjects) {
                isAuthorized = isAuthorized(user, targetObject, permission);
                if (!isAuthorized) break;
            }
            return isAuthorized;
        }
    }
}

My question is:

How I can handle collections using @PreAuthorize("hasPermission(#object, '...')") more elegant way? Is there some implementations in Spring Security for handling collections? At least, how can I optimize PemissionService for handling Collections?

Body:
I have a couple of workarounds.

1. The first one is to use my own MethodSecurityExpressionHandler and MethodSecurityExpressionRoot.

Creating a CustomMethodSecurityExpressionRoot and define a method which will be our new expression for Collection handling. It will extend SecurityExpressionRoot to include default expressions:

public class CustomMethodSecurityExpressionRoot extends SecurityExpressionRoot implements MethodSecurityExpressionOperations {

    private final PermissionEvaluator permissionEvaluator;
    private final Authentication authentication;

    private Object filterObject;
    private Object returnObject;
    private Object target;

    public CustomMethodSecurityExpressionRoot(Authentication authentication, PermissionEvaluator permissionEvaluator) {
        super(authentication);
        this.authentication = authentication;
        this.permissionEvaluator = permissionEvaluator;
        super.setPermissionEvaluator(permissionEvaluator);
    }

    public boolean hasAccessToCollection(Collection<Object> collection, String permission) {
        for (Object object : collection) {
            if (!permissionEvaluator.hasPermission(authentication, object, permission))
                return false;
        }
        return true;
    }

    @Override
    public void setFilterObject(Object filterObject) {
        this.filterObject = filterObject;
    }

    @Override
    public Object getFilterObject() {
        return filterObject;
    }

    @Override
    public void setReturnObject(Object returnObject) {
        this.returnObject = returnObject;
    }

    @Override
    public Object getReturnObject() {
        return returnObject;
    }

    @Override
    public Object getThis() {
        return target;
    }
}

Create custom expression handler and inject CustomMethodSecurityExpressionRoot:

public class CustomMethodSecurityExpressionHandler extends DefaultMethodSecurityExpressionHandler {

    private final PermissionEvaluator permissionEvaluator;

    public CustomMethodSecurityExpressionHandler(PermissionEvaluator permissionEvaluator) {
        this.permissionEvaluator = permissionEvaluator;
        super.setPermissionEvaluator(permissionEvaluator);
    }

    @Override
    protected MethodSecurityExpressionOperations createSecurityExpressionRoot(
            Authentication authentication, MethodInvocation invocation) {
        CustomMethodSecurityExpressionRoot root =
                new CustomMethodSecurityExpressionRoot(authentication, permissionEvaluator);
        root.setTrustResolver(new AuthenticationTrustResolverImpl());
        root.setRoleHierarchy(getRoleHierarchy());
        return root;
    }
}

I also injected SecurityPermissionEvaluator used in question, so it will be a single point of entry for custom and default expressions. As an alternate option we could inject and use PermissionService directly.

Configuring our method-level security:

@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {

    @Autowired
    private PermissionService permissionService;

    @Override
    protected MethodSecurityExpressionHandler createExpressionHandler() {
        PermissionEvaluator permissionEvaluator = new SecurityPermissionEvaluator(permissionService);
        return new CustomMethodSecurityExpressionHandler(permissionEvaluator);
    }
}

Now we can use new expression in RestController:

@PreAuthorize("hasAccessToCollection(#products, 'WRITE')")
@RequestMapping(value = "/saveCollection", method = RequestMethod.POST)
public Collection<Product> save(@RequestBody Collection<Product> products) {
    return productService.save(products);
}

As a result a part with handling collection in PermissionService could be omitted as we took out this logic to custom expression.

2. The second workaround is to call method directly using SpEL.

Now I'm using PermissionEvaluator as Spring bean (any service could be used here, but I'm preferring single point of entry again)

@Component
public class SecurityPermissionEvaluator implements PermissionEvaluator {

    @Autowired
    private PermissionService permissionService;

    @Override
    public boolean hasPermission(Authentication authentication, Object targetDomainObject, Object permission) {
        if (!(targetDomainObject instanceof TopAppEntity))
            throw new IllegalArgumentException();
        CustomUserDetails userDetails = (CustomUserDetails) authentication.getPrincipal();
        return permissionService.isAuthorized(userDetails.getUser(), targetDomainObject, permission.toString());
    }

    @Override
    public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, Object permission) {
        CustomUserDetails userDetails = (CustomUserDetails) authentication.getPrincipal();
        try {
            return permissionService.isAuthorized(userDetails.getUser(), targetId,
                    Class.forName(targetType), String.valueOf(permission));
        } catch (ClassNotFoundException e) {
            throw new IllegalArgumentException("No class found " + targetType);
        }
    }

    public boolean hasPermission(Authentication authentication, Collection<Object> targetDomainObjects, Object permission) {
        for (Object targetDomainObject : targetDomainObjects) {
            if (!hasPermission(authentication, targetDomainObject, permission))
                return false;
        }
        return true;
    }

}

Configuring method security:

@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {

    @Autowired
    private PermissionEvaluator permissionEvaluator;
    @Autowired
    private ApplicationContext applicationContext;

    @Override
    protected MethodSecurityExpressionHandler createExpressionHandler() {
        DefaultMethodSecurityExpressionHandler expressionHandler =
                new DefaultMethodSecurityExpressionHandler();
        expressionHandler.setPermissionEvaluator(permissionEvaluator);
        // Pay attention here, or Spring will not be able to resolve bean
        expressionHandler.setApplicationContext(applicationContext);
        return expressionHandler;
    }
}

Usage of the service in expression:

@PreAuthorize("@securityPermissionEvaluator.hasPermission(authentication, #products, 'WRITE')")
@RequestMapping(value = "/saveCollection", method = RequestMethod.POST)
public Collection<Product> save(@RequestBody Collection<Product> products) {
    return productService.save(products);
}

Spring beans created by default with class name if no other name specified.

Summary: both approaches based on using custom services calling them directly or registering them as expressions and could handle the logic of collection before it will be sent to authority checking service, so we can omit the part of it:

@Service
public class PermissionService {

    public boolean isAuthorized(User user, TopAppEntity domainEntity, String permission) {
        // removed instanceof checks and can operate on domainEntity directly
        if (domainEntity.getId() == null) {
            // check authorities and give response
        } else {
            // check ACL and give response
        }
    }
}


问:
Angular 2 : not able to render json
I am not able to render the following data in html and am getting an error. The console error is attach below the code. Currently I have single data in json, but it can be more in the future.

processNo

prodLine

modelYear

team_NO

vmc

Please help as I am new to this. I tried referring similar questions, but it didn't work for me.

/* json */

{
 "statuscode": 1,
 "message": "SUCESS",
 "template": null,
 "filter": {
  "controlNo": "25504",
  "processNo": "3A311",
  "plantCode": "T",
  "deptCode": "AF",
  "modelYear": "2017",
  "prodRate": "475",
  "prodLine": "3",
  "vmc": "A"
 }
}

/* controller */

constructor(private ReportServiceService:ReportServiceService) {   }

  ngOnInit() {
    this.safetySummary();
  }

  safetySummary(){
    return this.ReportServiceService.getSafetySummary().subscribe(
      res => this.res = res.json())
  }

/* Error Msg in console */

compiler.es5.js:1689 Uncaught Error: Template parse errors:
Can't bind to 'ngForIn' since it isn't a known property of 'div'. ("t Management - Process / Parts Summary

]*ngFor="let i in res.filter">

      ]

    <div class="row row-ite"): ng:///AppModule/ProcessPartSummaryComponent.html@166:2
    at syntaxError (http://localhost:4200/vendor.bundle.js:36022:34)
    at TemplateParser.webpackJsonp.../../../compiler/@angular/compiler.es5.js.TemplateParser.parse (http://localhost:4200/vendor.bundle.js:47134:19)
    at JitCompiler.webpackJsonp.../../../compiler/@angular/compiler.es5.js.JitCompiler._compileTemplate (http://localhost:4200/vendor.bundle.js:61179:39)
    at http://localhost:4200/vendor.bundle.js:61099:62
    at Set.forEach (native)
    at JitCompiler.webpackJsonp.../../../compiler/@angular/compiler.es5.js.JitCompiler._compileComponents (http://localhost:4200/vendor.bundle.js:61099:19)
    at http://localhost:4200/vendor.bundle.js:60986:19
    at Object.then (http://localhost:4200/vendor.bundle.js:36012:148)
    at JitCompiler.webpackJsonp.../../../compiler/@angular/compiler.es5.js.JitCompiler._compileModuleAndComponents (http://localhost:4200/vendor.bundle.js:60985:26)
    at JitCompiler.webpackJsonp.../../../compiler/@angular/compiler.es5.js.JitCompiler.compileModuleAsync (http://localhost:4200/vendor.bundle.js:60914:37)```
<pre class="snippet-code-html lang-html prettyprint-override"><code><div class="container-fluid report-details" *ngFor="let i in res.filter">
    <div class="row row-item">
      <div class="col-lg-6 col-md-6 col-sm-6 report-detail-table">
          <span class="width-twenty bold">Process No.:</span>
          <span class="width-thirty">{{i.processNo}}</span>
          <span class="width-ten bold">Line:</span>
          <span class="width-forty">3</span>
      </div>
      <div class="col-lg-6 col-md-6 col-sm-6 report-detail-table">
          <span class="width-thirty bold">Model Cycle:</span>
          <span class="width-seventy">2017</span>
      </div>
    </div>
    <div class="row row-item">
      <div class="col-lg-6 col-md-6 col-sm-6 report-detail-table">
          <span class="width-twenty bold">Team:</span>
          <span class="width-thirty">DL01</span>
          <span class="width-ten bold">VMC:</span>
          <span class="width-forty">3</span>
      </div>
      <div class="col-lg-6 col-md-6 col-sm-6 report-detail-table">
          <span class="width-thirty bold">Part Effective Date:</span>
          <span class="width-seventy">05/30/2017</span>
      </div>
    </div>
    <div class="row row-item">
      <div class="col-lg-6 col-md-6 col-sm-6 report-detail-table">
          <span class="width-twenty bold">Process Name:</span>
          <span class="width-forty">RIGHT FRONT HARNESS INSTALL</span>
          <span class="width-forty"></span>
      </div>
      <div class="col-lg-6 col-md-6 col-sm-6 report-detail-table">
          <span class="width-thirty bold">Body/Line Loc:</span>
          <span class="width-seventy">D01R</span>
      </div>
    </div>
  </div></code>```

答:
```<code>let i in res.filter
</code>```

should be

```<code>let i of res.filter
</code>```

I've made this mistake multiple times.

Title: Angular 2 : not able to render json

Body:
I am not able to render the following data in html and am getting an error. The console error is attach below the code. Currently I have single data in json, but it can be more in the future.

processNo

prodLine

modelYear

team_NO

vmc

Please help as I am new to this. I tried referring similar questions, but it didn't work for me.

/* json */

{
 "statuscode": 1,
 "message": "SUCESS",
 "template": null,
 "filter": {
  "controlNo": "25504",
  "processNo": "3A311",
  "plantCode": "T",
  "deptCode": "AF",
  "modelYear": "2017",
  "prodRate": "475",
  "prodLine": "3",
  "vmc": "A"
 }
}

/* controller */

constructor(private ReportServiceService:ReportServiceService) {   }

  ngOnInit() {
    this.safetySummary();
  }

  safetySummary(){
    return this.ReportServiceService.getSafetySummary().subscribe(
      res => this.res = res.json())
  }

/* Error Msg in console */

compiler.es5.js:1689 Uncaught Error: Template parse errors:
Can't bind to 'ngForIn' since it isn't a known property of 'div'. ("t Management - Process / Parts Summary

]*ngFor="let i in res.filter">

      ]

    <div class="row row-ite"): ng:///AppModule/ProcessPartSummaryComponent.html@166:2
    at syntaxError (http://localhost:4200/vendor.bundle.js:36022:34)
    at TemplateParser.webpackJsonp.../../../compiler/@angular/compiler.es5.js.TemplateParser.parse (http://localhost:4200/vendor.bundle.js:47134:19)
    at JitCompiler.webpackJsonp.../../../compiler/@angular/compiler.es5.js.JitCompiler._compileTemplate (http://localhost:4200/vendor.bundle.js:61179:39)
    at http://localhost:4200/vendor.bundle.js:61099:62
    at Set.forEach (native)
    at JitCompiler.webpackJsonp.../../../compiler/@angular/compiler.es5.js.JitCompiler._compileComponents (http://localhost:4200/vendor.bundle.js:61099:19)
    at http://localhost:4200/vendor.bundle.js:60986:19
    at Object.then (http://localhost:4200/vendor.bundle.js:36012:148)
    at JitCompiler.webpackJsonp.../../../compiler/@angular/compiler.es5.js.JitCompiler._compileModuleAndComponents (http://localhost:4200/vendor.bundle.js:60985:26)
    at JitCompiler.webpackJsonp.../../../compiler/@angular/compiler.es5.js.JitCompiler.compileModuleAsync (http://localhost:4200/vendor.bundle.js:60914:37)

          Process No.:
          {{i.processNo}}
          Line:
          3

          Model Cycle:
          2017

          Team:
          DL01
          VMC:
          3

          Part Effective Date:
          05/30/2017

          Process Name:
          RIGHT FRONT HARNESS INSTALL

          Body/Line Loc:
          D01R

Body:
let i in res.filter

should be

let i of res.filter

I've made this mistake multiple times.