PostSharp - Applying aspect to mscorlib but prohibit modifying calls in my own class - .net-assembly

My aspect:
[Serializable]
class DumbLogger : OnMethodBoundaryAspect
{
public override void OnEntry(MethodExecutionArgs args)
{
Log.Print("Entry: ") + args.Method.Name;
args.FlowBehavior = FlowBehavior.Continue;
}
}
This is what i am using to modify the calls in mscorlib AND trying to exclude them from being modified in my class called LOG
[assembly: MY_PROJECT.DumbLogger(
AttributeTargetTypes = "MY_PROJECT.Log",
AttributeExclude = true,
AttributePriority = 1)]
[assembly: MY_PROJECT.DumbLogger(
AttributeTargetAssemblies = "mscorlib",
AttributePriority = 2)]
But.. This doesnt do the trick because if i look at my LOG class with ILspy decompiler i can see method calls to any class # mscorlib.dll being modified for example:
<>z__Aspects.<System.Object.ToString>b__v(text)
The reason i wanna do this is because when i enter the method Log.Print it will generate a stackoverflow exception and will infinitely call itself.
I am already aware of maybe excluding certain namespaces and classes like string from mscorlib but i have my reasons to do it the way i described.

PostSharp Aspects in general are applied to declarations (assemblies, types, methods, parameters, fields, etc.). When you are applying an MethodLevelAspect (base class of OnMethodBoundaryAspect) on an external method, PostSharp transforms the call site (call instruction in IL), but still thinks of the aspect as being on the declaration itself.
There is currently no way to filter by call site and it would require a different kind of aspect and/or advices. Therefore your AttributeExclude=true specifying attribute on the assembly does not have any effect as it says that the aspect should not be applied on Log type, which it is not.
The common technique that solves exactly this case is to use a ThreadStatic variable to break the recursion cycle as the following code demonstrates:
[Serializable]
class DumbLogger : OnMethodBoundaryAspect
{
[ThreadStatic] private static bool logging;
public override void OnEntry(MethodExecutionArgs args)
{
if (logging)
return;
try
{
logging = true;
Log.Print("Entry: " + args.Method.Name);
args.FlowBehavior = FlowBehavior.Continue;
}
finally
{
logging = false;
}
}
}
Please also note that MethodInterception and OnMethodBoundary aspects are the only aspect that work on external assemblies.

Related

Throw specific exception for a violation of a contract on an automatic property

I can specify a contract for an automatic property like this (example taken from the CC documentation):
public int MyProperty { get; set ; }
[ContractInvariantMethod]
private void ObjectInvariant () {
Contract. Invariant ( this .MyProperty >= 0 );
...
}
When runtime-checking is turned on, and an attempt is made to assign an invalid value to MyProperty, the setter throws System.Diagnostics.Contracts.__ContractsRuntime+ContractException.
Is there a way to make it throw a specific type of exception - typically, ArgumentNullException, ArgumentOutOfRangeException, or similar, without having to go back and implement the property manually using a backing field and Requires<> ?
No, there isn't.
But as long as your property setter is private, you don't have to worry about that. Any ArgumentException that would be thrown from your setter indicates a bug in the code calling that setter, and should be fixed there. The only code that can call your setter is your own.
If your property setter is protected or public, then you do need to specify which ArgumentException gets thrown for which values.
From the Code Contracts manual:
Object invariants are conditions that should hold true on each instance of a class whenever that object is visible to a client. They express conditions under which the object is in a "good" state.
There's a peculiar couple of sentences in the manual at the top of page 10:
Invariants are conditionally defined on the full-contract symbol [CONTRACT_FULL]. During runtime checking, invariants are checked at the end of each public method. If an invariant mentions a public method in the same class, then the invariant check that would normally happen at the end of that public method is disabled and checked only at the end of the outermost method call to that class. This also happens if the class is re-entered because of a call to a method on another class.
— text in brackets is mine; this is the compile time symbol the manual is referencing which is defined.
Since properties are really just syntactic sugar for T get_MyPropertyName() and void set_MyPropertyName(T), these sentences would seem to apply to properties, too. Looking in the manual, when they show an example of defining object invariants, thy show using private fields in the invariant contract conditions.
Also, invariants don't really communicate to consumers of your library what the pre-conditions or post-conditions for any particular property or method are. Invariants, again, only state to consumers of the library what conditions "hold true on each instance of a class whenever that object is visible to a client." That's all they do. In order to state that if an invalid value will result in throwing an exception, you must specify a pre-condition, which is demonstrated below.
Therefore, it would appear that in order to best achieve what you're looking for, it's as hvd says: it's best to have a private backing field and place the invariant on the backing field. Then you would also provide the contracts on the property getter/setter so that consumers of your library know what the pre-conditions and guaranteed post-conditions (if any) are.
int _myPropertyField = 0;
[ContractInvariantMethod]
private void ObjectInvariants()
{
Contract.Invariant(_myPropertyField >= 0);
}
public int MyProperty
{
get
{
Contract.Ensures(Contract.Result<int>() >= 0);
return _myPropertyField;
}
set
{
Contract.Requires<ArgumentOutOfRangeException>(value >= 0);
_myPropertyField = value;
}
}
Now, there is another way to throw a specific exception using "legacy" code contracts (e.g. if-then-throw contracts). You would use this method if you're trying to retrofit contracts into an existing codebase that was originally written without contracts. Here's how you can do this without using Contract.Requires<TException>(bool cond):
Basically, in Section 5: Usage Guidelines of the manual, you'll be referencing Usage Scenario 3, legacy contract checking (see page 20). This means you need to set the following options in the Code Contracts project properties dialog:
Ensure that the Assembly Mode is set to Custom Parameter Validation.
Use "if-then-throw" guard blocks and perform manual inheritance.private
Ensure Contract.EndContractBlock() follows these guard blocks.
Check Perform Runtime Contract Checking and select the level of checking you want, but only on Debug builds—not on Release builds.
Feel free to use Contract.Requires(bool cond) (non-generic form) on private API methods (e.g. methods not directly callable by a library consumer).
Then, you could write the following code:
private int _myPropertyField = 0;
[ContractInvariantMethod]
private void ObjectInvariants()
{
Contract.Invariant(_myPropertyField >= 0);
}
public int MyProperty
{
get
{
Contract.Ensures(Contract.Result<int>() >= 0);
return _myPropertyField;
}
set
{
if (value < 0)
{
throw new ArgumentOutOfRangeException("value");
}
Contract.EndContractBlock();
_myPropertyField = value;
}
}
Now, you specifically stated that you didn't want to have to go back and create private backing fields for all of your properties. Unfortunately, if this is a public property than can be mutated, then there really is no way to good avoid this. One possible way to avoid this, though, is to make your setter private:
public int MyProperty { get; private set; }
[ContractInvariantMethod]
private void ObjectInvariants()
{
Contract.Invariant(MyProperty >= 0);
}
public SetMyProperty(int value)
{
// Using Code Contracts with Release and Debug contract checking semantics:
Contract.Requires<ArgumentOutOfRangeException>(value >= 0);
// Or, using Code Contracts with Debug-only contract checking semantics:
Contract.Requires(value >= 0);
// Using Legacy contracts for release contract checking without throwing
// a ContractException, but still throwing a ContractException for
// debug builds
if (value < 0)
{
throw new ArgumentOutOfRangeException(nameof(value));
}
Contract.EndContractBlock();
MyProperty = value;
}
However, I must admit, I'm not really sure what you're gaining at this point by implementing invariants in this manner. You might as well just bite the bullet and use one of the first two examples I demonstrated above.
Addendum, 2016-02-22
The OP notes in their comment that Section 2.3.1 of the manual mentions that defining object invariants on auto-properties results in the invariant essentially becoming a precondition on the setter and a postcondition on the getter. That's correct. However, the preconditions that are created use the non-generic Contract.Requires(bool condition) form. Why? So that when invariants are used by those who don't want runtime contract checking turned on for their Release builds, they can still use invariants. Therefore, even if you use invariants on properties, if you want a specific exception thrown on contract violations, you must use full properties with backing fields and the generic form of Requires, which also implies that you want to perform runtime contract checking on all builds, including Release builds.

Error while building the solution in vs2012?

I've created my project in vs2008.It works fine.But when i opened the solution and try to build it in vs2012 i am getting the following error in TransactionDB.dbml page.
a partial method may not have multiple defining declarations
What could be the problem??
.net supports partial methods.
It means you write a definition in one part of the partial class and the implementation in another. Like this:
partial class MyClass
{
partial void MyPartialMethod(string s);
}
// This part can be in a separate file.
partial class MyClass
{
// Comment out this method and the program will still compile.
partial void MyPartialMethod(string s)
{
Console.WriteLine("Something happened: {0}", s);
}
}
In your case I you have the two definitions of the partial method causing the compiler to fail.
Source MSDN
The defining declaration of a partial method is the part that specifies the method signature, but not the implementation (method body). A partial method must have exactly one defining declaration for each unique signature. Each overloaded version of a partial method must have its own defining declaration.
To correct this error
Remove all except one defining declaration for the partial method.
Example
// cs0756.cs
using System;
public partial class C
{
partial void Part();
partial void Part(); // CS0756
public static int Main()
{
return 1;
}
}

Can I use something like DebuggerTypeProxyAttribute on a type that I don't own?

I've got an IClaimsPrincipal variable, and I'd like to see how many claims are in it. Navigating through the properties in the watch window is complicated, so I'd like to customize how this object is displayed.
I'm aware of the [DebuggerTypeProxy] attribute, which initially looked like it might do what I want. Unfortunately, it needs to be attached to the class, and I don't "own" the class. In this case it's a Microsoft.IdentityModel.Claims.ClaimsPrincipal.
I'd like to display the value of IClaimsPrincipal.Identities[0].Claims.Count.
Is there any way, using [DebuggerTypeProxy] or similar, to customize how the value of a type that I don't own is displayed in the watch window?
Example of DebuggerTypeProxyAttribute applied to KeyValuePair showing only the Value member:
using System.Collections.Generic;
using System.Diagnostics;
[assembly: DebuggerTypeProxy(typeof(ConsoleApp2.KeyValuePairDebuggerTypeProxy<,>), Target = typeof(KeyValuePair<,>))]
// alternative format [assembly: DebuggerTypeProxy(typeof(ConsoleApp2.KeyValuePairDebuggerTypeProxy<,>), TargetTypeName = "System.Collections.Generic.KeyValuePair`2")]
namespace ConsoleApp2
{
class KeyValuePairDebuggerTypeProxy<TKey, TValue>
{
private KeyValuePair<TKey, TValue> _keyValuePair; // beeing non-public this member is hidden
//public TKey Key => _keyValuePair.Key;
public TValue Value => _keyValuePair.Value;
public KeyValuePairDebuggerTypeProxy(KeyValuePair<TKey, TValue> keyValuePair)
{
_keyValuePair = keyValuePair;
}
}
class Program
{
static void Main(string[] args)
{
var dictionary = new Dictionary<int, string>() { [1] = "one", [2] = "two" };
Debugger.Break();
}
}
}
Tested on Visual Studio 2017
The best I've come up with so far is to call a method:
public static class DebuggerDisplays
{
public static int ClaimsPrincipal(IClaimsPrincipal claimsPrincipal)
{
return claimsPrincipal.Identities[0].Claims.Count;
}
}
...from the watch window:
DebuggerDisplays.ClaimsPrincipal(_thePrincipal),ac = 10
The ",ac" suppresses the "This expression causes side effects and will not be evaluated".
However, note that when this goes out of scope, Visual Studio will simply grey out the watch window entry, even with the ",ac". To avoid this, you'll need to ensure that everything is fully qualified, which means that you'll end up with extremely long expressions in the watch window.

C# 4, COM interop and UPnP: A trying triumvirate

I'm trying to write a bit of code (just for home use) that uses UPnP for NAT traversal, using C# 4 and Microsoft's COM-based NAT traversal API (Hnetcfg.dll).
Unfortunately (or perhaps fortunately) the last time I had to do COM interop in .NET was sometime around the last ice age, and I seem to be fundamentally confused about C#'s use of dynamic types for interop and how to write a callback (so that the COM server calls my managed code).
Here's an exciting few lines of code:
// Referencing COM NATUPNPLib ("NATUPnP 1.0 Type Library")
using System;
using NATUPNPLib;
class NATUPnPExample
{
public delegate void NewNumberOfEntriesDelegate(int lNewNumberOfEntries);
public static void NewNumberOfEntries(int lNewNumberOfEntries)
{
Console.WriteLine("New number of entries: {0}", lNewNumberOfEntries);
}
public static void Main(string[] args)
{
UPnPNAT nat = new UPnPNAT();
NewNumberOfEntriesDelegate numberOfEntriesCallback = NewNumberOfEntries;
nat.NATEventManager.NumberOfEntriesCallback = numberOfEntriesCallback;
nat.StaticPortMappingCollection.Add(4555, "TCP", 4555, "192.168.0.1", true, "UPnPNAT Test");
// Presumably my NewNumberOfEntries() method should be called by the COM component about now
nat.StaticPortMappingCollection.Remove(4555, "TCP");
}
}
In the above code, the Add and Remove calls work absolutely fine. Terrific.
The trouble is, I would also like to know when the number of port mapping entries have changed, and to do so I need to register a callback interface (INATEventManager::put_NumberOfEntriesCallback), which must support the INATNumberOfEntriesCallback or IDispatch interfaces. VS2012's object browser describes INATEventManager::put_NumberOfEntriesCallback thusly:
dynamic NumberOfEntriesCallback { set; }
Right, so I was under the impression that in C# 4 I shouldn't have to decorate anything with fancy attributes and that I can register my callback simply by jamming a delegate into INATEventManager::put_NumberOfEntriesCallback in a vulgar manner and leaving .NET to worry about IDispatch and clear up the mess; but it appears that I'm terribly wrong.
So, er... What should I do to ensure my NewNumberOfEntries method is called?
I'm also slightly concerned that I can write nat.NATEventManager.NumberOfEntriesCallback = 1; or nat.NATEventManager.NumberOfEntriesCallback = "Sausages"; without an exception being thrown.
It seems that I was able to make it work. Two options - with a custom interface "INATNumberOfEntriesCallback" (which does not seem to be declared in the type library btw, you need to declare it yourself) and using plain dispatch with DispId(0). The conversion to the IDispatch/IUnknown is preformed by the framework automatically. So:
Option 1.
Declare the INATNumberOfEntriesCallback and make a callback class which implements that interface (the tricky part is Guid - it comes from the "Natupnp.h" file, and does not seem to appear to be in the type library).
// declare INATNumberOfEntriesCallback interface
[ComVisible(true)]
[Guid("C83A0A74-91EE-41B6-B67A-67E0F00BBD78")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface INATNumberOfEntriesCallback
{
void NewNumberOfEntries(int val);
};
// implement callback object
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.None)]
public class CallbackNewNumberOfEntries : INATNumberOfEntriesCallback
{
public void NewNumberOfEntries(int val)
{
Console.WriteLine("Number of entries changed: {0}", val);
}
}
class NATUPnPExample
{
public static void Main(string[] args)
{
var nat = new UPnPNAT();
nat.NATEventManager.NumberOfEntriesCallback = new CallbackNewNumberOfEntries();
nat.StaticPortMappingCollection.Add(4555, "TCP", 4555, "192.168.0.1", true, "UPnPNAT Test");
// Presumably my NewNumberOfEntries() method should be called by the COM component about now
nat.StaticPortMappingCollection.Remove(4555, "TCP");
}
}
Option 2.
Use plain dispatch. The documentation says that you can use dispid(0) and it should be called, with 4 (!) parameters (see the remarks section in docs). So basically the following construction seems to work in "dispatch" way:
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.AutoDispatch)]
public class CallbackDisp
{
[DispId(0)]
public void OnChange(string updateType, object obj, object name, object val)
{
Console.WriteLine("{0}: {1} = {2}", updateType, name, val);
}
}
class NATUPnPExample
{
public static void Main(string[] args)
{
var nat = new UPnPNAT();
nat.NATEventManager.NumberOfEntriesCallback = new CallbackDisp();
nat.StaticPortMappingCollection.Add(4555, "TCP", 4555, "192.168.0.1", true, "UPnPNAT Test");
// Presumably my NewNumberOfEntries() method should be called by the COM component about now
nat.StaticPortMappingCollection.Remove(4555, "TCP");
}
}
I had the same problem you had, and since there isn't much help on the topic your posting helped tremendously! It wouldn't let me comment on your answer because I don't have enough points or whatever but your answer is the best, but doesn't quite work how I thought it would.
nat.NATEventManager.ExternalIPAddressCallback = new CallbackDisp();
Works, using the same dispatch, and will tell you when the external IP changes. HOWEVER,
nat.NATEventManager.NumberOfEntriesCallback = new CallbackDisp();
only reports UPnP map changes from these conditions: A.) It was added/removed by the NATUPnP instance.. In this case:
nat.StaticPortMappingCollection.Add();
OR B.) it was already mapped when the instance was created:
var nat = new UPnPNAT();
As an example, if Utorrent was running when you started your program and you you had something to block the program from exiting(Console.WriteLine();) for example.. When you exit Utorrent the callback would fire, and notify you of the map changes. Which is exactly what I wanted in the first place. However, if you re-open Utorrent, or any other app that uses UPnP it will NOT fire the callback, and will not notify you of the change.
Needless to say it has been very frustrating. If you figure it out please share! I know I can easily implement the functionality by polling the StaticPortMappingCollection at a given interval, but it seems a little 'hacky' to me.

How to force the order of Installer Execution

I have been building a new .NET solu­tion with Cas­tle per­form­ing my DI.
Its now at the stage where i would like to con­trol the order in which my installers run. I have built indi­vid­ual classes which implement IWind­sorIn­staller to han­dle my core types — eg IRepos­i­tory, IMap­per and ISer­vice to name a few.
I see that its suggested i implement my own Installer­Fac­tory (guessing i just override Select) in this class.
Then use this new factory in my call to:
FromAssembly.InDirectory(new AssemblyFilter("bin loca­tion"));
My ques­tion — when over­rid­ing the save method — what is the best way to force the order of my installers.
I know its already solved but I couldn't find any example on how to actually implement the InstallerFactory so here's a solution if anyone is googling for it.
How to use:
[InstallerPriority(0)]
public class ImportantInstallerToRunFirst : IWindsorInstaller
{
public void Install(IWindsorContainer container, Castle.MicroKernel.SubSystems.Configuration.IConfigurationStore store)
{
// do registrations
}
}
Just add the InstallerPriority attribute with a priority to your "install-order-sensitive" classes. Installers will be sorted by ascending. Installers without priority will default to 100.
How to implement:
public class WindsorBootstrap : InstallerFactory
{
public override IEnumerable<Type> Select(IEnumerable<Type> installerTypes)
{
var retval = installerTypes.OrderBy(x => this.GetPriority(x));
return retval;
}
private int GetPriority(Type type)
{
var attribute = type.GetCustomAttributes(typeof(InstallerPriorityAttribute), false).FirstOrDefault() as InstallerPriorityAttribute;
return attribute != null ? attribute.Priority : InstallerPriorityAttribute.DefaultPriority;
}
}
[AttributeUsage(AttributeTargets.Class)]
public sealed class InstallerPriorityAttribute : Attribute
{
public const int DefaultPriority = 100;
public int Priority { get; private set; }
public InstallerPriorityAttribute(int priority)
{
this.Priority = priority;
}
}
When starting application, global.asax etc:
container.Install(FromAssembly.This(new WindsorBootstrap()));
You can call your installers in the order they need to be instantiated in Global.asax.cs or e.g. in a Bootstrapper class, which is called from Global.asax.cs.
IWindsorContainer container = new WindsorContainer()
.Install(
new LoggerInstaller() // No dependencies
, new PersistenceInstaller() // --""--
, new RepositoriesInstaller() // Depends on Persistence
, new ServicesInstaller() // Depends on Repositories
, new ControllersInstaller() // Depends on Services
);
They are instantiated in this order, and you can add a breakpoint after and check the container for "Potentially misconfigured components".
If there are any, check their Status->details, if not, it's the correct order.
This solution is quick and easy, the documentation mentions using a InstallerFactory Class for tighter control over your installers so if you have a ton of installers the other solution may fit better. (Using code as convention should not require tons of installers?)
http://docs.castleproject.org/Windsor.Installers.ashx#codeInstallerFactorycode_class_4
In the end i had to use InstallerFactory and implement the ordering rules as suggested previously by returning the IEnumerable<Type> with my specific order

Resources