I'm using Ninject and AOP to do some caching. I have a Attribute that I can apply to any method in my repository and on BeforeInvoke it will return my cached Object if there is one and AfterInvoke create a cached object. This all works great but I can't figure out how to stop initial method from being called, ie if there is a cached object the return that instead of calling a the intyercepted method. My interceptor is here:
public class CacheInterceptor : SimpleInterceptor
{
protected override void BeforeInvoke(IInvocation invocation)
{
Type returnType = invocation.Request.Method.ReturnType;
string cacheKey = CacheKeyBuilder.GetCacheKey(invocation, serializer);
object cachedValue = cache.Get(cacheKey);
if (cachedValue == null)
{
invocation.Proceed();
}
else
{
object returnValue = serializer.Deserialize(returnType, cachedValue);
invocation.ReturnValue = returnValue;
returnedCachedResult = true;
}
}
}
Even though in the else statement I am clearly not saying to call the invoked Method 'invocation.Proceed();' it still invokes it. How do I tell ninject to just return with the invocation.ReturnValue ?
You can't use SimpleInterceptor in this case because that is meant as base class for the most common scenario where you want to do an action before or after the actual method call. Also you are not allowed to call Proceed Instead implement the IInterceptor interface and put your code into the Intercept method.
But probably we should extend SimpleInterceptor in a future version so that you can prevent that the actual method is called:
public abstract class SimpleInterceptor : IInterceptor
{
private bool proceedInvocation = true;
/// <summary>
/// Intercepts the specified invocation.
/// </summary>
/// <param name="invocation">The invocation to intercept.</param>
public void Intercept( IInvocation invocation )
{
BeforeInvoke( invocation );
if (proceedInvocation)
{
invocation.Proceed();
AfterInvoke( invocation );
}
}
/// <summary>
/// When called in BeforeInvoke then the invokation in not proceeded anymore.
/// Or in other words the decorated method and AfterInvoke won't be called anymore.
/// Make sure you have assigned the return value in case it is not void.
/// </summary>
protected void DontProceedInvokation()
{
this.proceedInvocation = false;
}
/// <summary>
/// Takes some action before the invocation proceeds.
/// </summary>
/// <param name="invocation">The invocation that is being intercepted.</param>
protected virtual void BeforeInvoke( IInvocation invocation )
{
}
/// <summary>
/// Takes some action after the invocation proceeds.
/// </summary>
/// <param name="invocation">The invocation that is being intercepted.</param>
protected virtual void AfterInvoke( IInvocation invocation )
{
}
}
Related
I have a long running operation in my Winforms project. I am calling a long running synchronization operation from one to another class.
So, In Class1, I am performing a single run of the synchronization operation and calling synchronizer.Synchronize(); which is implemented in Class2.
Any type of MemberShipSynchronization service interupption or Stopped is disposed in Class1 in its Dispose().
From Class2, I am calling the populator.PopulateMembership(); which is implemented in Class3, So, the PopulateMembership() in class3 is long running process.
I want to make this operation Cancellable, means, I want to send the CancellableToken from Class1 to Class3 based on MemberShipSynchronization Service request ( i.e. Stop/Interuppted) and
when the long running operation in Class3 receive the Cancellation request that time I want to Cancel this operation.
So finally, I want to handle this operation gracefully in Class1.
Please suggest a better workaround to achieve this.
=>Class1.
public sealed class MembershipSynchronizationService : IDisposable
{
private readonly object _sync = new object();
/// <summary>
/// Performs a single run of the synchronization service.
/// </summary>
public void RunOnce()
{
lock (_sync)
{
var synchronizer = new MembershipSynchronizer(MembershipManagerUnsecured.SoleInstance.MembershipManager);
synchronizer.Synchronize();
}
}
#region Dispose pattern
/// <summary>
/// Finalizer. Cleans up resources.
/// </summary>
~MembershipSynchronizationService()
{
Dispose(false);
}
/// <summary>
/// Cleans up resources.
/// </summary>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
/// <summary>
/// Cleans up resources.
/// </summary>
private void Dispose(bool disposing)
{
if (disposing)
{
lock (_sync)
{
// nothing to do
_ = this;
}
}
}
#endregion
}
=> Class2.
internal sealed class MembershipSynchronizer
{
/// <summary>
/// Performs a single run of the synchronization service.
/// </summary>
public void Synchronize()
{
try
{
TimeSpan elapsed;
var stopwatch = Stopwatch.StartNew();
var populator = _membershipPopulatorFactory.CreatePopulator();
populator.PopulateMembership(); // Time consuming operation.
}
catch (Exception e)
{
LoggingUtility.LogTrace(LoggingCategory.Membership, e);
}
}
=> Class3.
/// <summary>
/// The main implementation of the membership populator.
/// </summary>
public sealed class Populator : IDisposable, IMembershipPopulator
{
public void PopulateMembership()
{
// Code for some time consuming operations.
// ........................................
// ........................................
// ........................................
}
}
}
I have the following logger logger class and I want to know the best to unit testing it.
Some observations:
I needed to create the interface IFileWrapper in order to break dependency with System.IO dependency and been able to user dependency injection (Autofac)
I was able to unit testing the method FileWrapper.WriteLog by implementing IFileWrapper using a MemoryString but if I wanted to test a expected behavior inside the method I won't be able (e.g: throwing exceptions, incorrect path and filename, etc.)
/// <summary>
/// Creates an instance of type <see cref="FileLogger"/>
/// </summary>
/// <remarks>Implements the Singleton Pattern</remarks>
private FileLogger()
{
FileName = string.Format("\\{0: MMM dd, yy}.log", DateTime.Now);
Path = Environment.CurrentDirectory;
FileWrapper = ContainerBuilderFactory.Container.Resolve<IFileWrapper>();
}
/// <summary>
/// Log the <paramref name="Message"/> in the <paramref name="Path"/> specified.
/// The <paramref name="UserName"/>, <paramref name="Host"/> must be supplied
/// </summary>
/// <example>
/// <code>
/// var handler = new LoggerHandlerFactory();
/// var logger = handler.GetHandler<FileLogger>();
/// logger.Log("Hello CSharpLogger");
/// </code>
/// </example>
/// <exception cref="ArgumentNullException"></exception>
/// <exception cref="ArgumentException"></exception>
/// <exception cref="NotSupportedException"></exception>
/// <exception cref="FileNotFoundException"></exception>
/// <exception cref="IOException"></exception>
/// <exception cref="SecurityException"></exception>
/// <exception cref="DirectoryNotFoundException"></exception>
/// <exception cref="UnauthorizedAccessException"></exception>
/// <exception cref="PathTooLongException"></exception>
/// <exception cref="ArgumentOutOfRangeException"></exception>
/// <exception cref="FormatException"></exception>
public void Log(string message, LogLevel level = LogLevel.INFO)
{
lock (_current)
{
var configLevel = CSharpLoggerConfiguration.Configuration.GetLogLevel();
if (configLevel != LogLevel.OFF & level != LogLevel.OFF && configLevel >= level)
{
try
{
FileWrapper.WriteLog(string.Concat(Path, FileName), message, level);
}
catch (CSharpLoggerException)
{
throw;
}
}
}
}
So, I created the following UnitTesting using Moq:
//arrange
CSharpLoggerConfiguration.Configuration.SetLogLevel(LogLevel.DEBUG);
var mock = new Mock<IFileWrapper>();
mock.Setup(x => x.WriteLog(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<LogLevel>()));
logger.FileWrapper = mock.Object;
//act
logger.Log("Hello CSharpLogger", LogLevel.DEBUG);
logger.Log("Hello CSharpLogger", LogLevel.WARN);
//assert
mock.Verify(x => x.WriteLog(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<LogLevel>()), Times.Exactly(2));
So far so good. What I'm not confortable is with this line: logger.FileWrapper = mock.Object; I would like to keep FileWrapper propety private.
Any advise is welcome.
I'll be publishing the code http://csharplogger.codeplex.com/ in case you want more details.
Use constructor injection. In short; instead of providing the service (in this case the file wrapper) by setting a property, make the logger have a public constructor which takes an IFileWrapper argument.
public class Logger
{
public Logger(IFileWrapper fileWrapper)
{
FileWrapper = fileWrapper;
}
public IFileWrapper FileWrapper { get; }
}
// in your test:
var logger = new Logger(mock.Object);
To answer the question about having a singleton file wrapper more thoroughly, here's a code sample for the application (non-test) code:
public static class FileWrapperFactory
{
private static IFileWrapper _fileWrapper;
public static IFileWrapper GetInstance()
{
return _fileWrapper ?? (_fileWrapper = CreateInstance());
}
private static IFileWrapper CreateInstance()
{
// do all the necessary setup here
return new FileWrapper();
}
}
public class StuffDoer
{
public void DoStuff()
{
var logger = new FileLogger(FileWrapperFactory.GetInstance());
logger.WriteLog("Starting to do stuff...");
// do stuff
logger.WriteLog("Stuff was done.");
}
}
Since the FileWrapperFactory maintains a static instance of the file wrapper, you'll never have more than one. However, you can create multiple loggers like that, and they don't have to care. If you, in the future, decide that it's OK to have many file wrappers, the logger code doesn't have to change.
In a real-world application, I'd advice you to choose some kind of DI framework to handle all this book-keeping for you; most have excellent support for singleton instances, doing essentially what the FileWrapperFactory above does (but usually in a more sophisticated and robust way. FileWrapperFactory isnt' thread-safe, for example...).
Since your code comments show that your logger is a singleton, you need a way other than constructor injection for setting the dependency. In his book on Legacy Code, Mike Feathers suggests a function for such purposes, which is adequately named, something like
public void SetInstanceForTesting(IFileWrapper fileWrapper) {...}
Now this function won't hopefully be used for different purposes...
I have the following code:
public partial class AuditLog : IBusinessEntity
{
public BusinessEntityType EntityType { get { return BusinessEntityType.AuditLog; } }
/// <summary>
/// Constructor accepting parameter initialization arguments
/// </summary>
/// <param name="userName"></param>
/// <param name="entity"></param>
/// <param name="command"></param>
/// <param name="commandText"></param>
public AuditLog(string userName, BusinessEntityType entity, AuditLogCommand command, string commandText)
{
this.Timestamp = DateTime.Now;
this.UserName = userName;
this.Entity = entity.ToString();
this.Command = command.ToString();
this.CommandText = commandText;
}
}
This is generating a CA2214 warning. The BusinessEntityType and AuditLogCommand method parameters are both enumerations. I don't see what the issue is here, and therefore am not certain how to satisfy the warning.
Thanks.
Is one or more of your properties virtual ? Then that is why, since CA2214 is the "Do not call overridable methods in constructors" warning.
Here is the reasoning for the rule from MSDN:
When a virtual method is called, the
actual type that executes the method
is not selected until run time. When a
constructor calls a virtual method, it
is possible that the constructor for
the instance that invokes the method
has not executed.
What this means is that if someone inherits from your class, and overrides a method or property that is accessed in your constructor - then the overriding implementation will be hit before the constructor for the inherited class has run. This might lead to problems if the overriding implementation relies on state set in the constructor.
To satisfy the warning, you need to make the properties and methods accessed in the constructor non-virtual (you could make the type sealed, if appropiate).
I have a NativeActivity derived activity that I wrote that is to use bookmarks as a trigger for a pick branch. Using something I found on MSDN I tried writing this to trigger the branch. The branch contains activities that fire service callbacks to remote clients via send activities. If I set a delay for the trigger, callbacks fire to the clients successfully. If I use my code activity, the pick branch activities don't fire.
public sealed class UpdateListener : NativeActivity<ClientUpdate>
{
[RequiredArgument]
public InArgument<string> BookmarkName { get; set; }
protected override void Execute(NativeActivityContext context)
{
context.CreateBookmark(BookmarkName.Get(context),
new BookmarkCallback(this.OnResumeBookmark));
}
protected override bool CanInduceIdle
{
get { return true; }
}
public void OnResumeBookmark(NativeActivityContext context, Bookmark bookmark, object obj )
{
Result.Set(context, (ClientUpdate)obj);
}
}
So it takes an arg to set the bookmark name for future bookmark references to execute the trigger. OnResumeBoookmark() takes in a ClientUpdate object that is passed by my application that is hosting the workflowapp. The activity is to return the object so the ClientUpdate can be passed to the workflow and have it sent to the remote clients via the send activity in the pick branch. In theory anyways.
For some reason it seems to be correct but feels wrong. I'm not sure if I should write the Activity in a different way to take care of what I need for my WF service.
I think your intentions would be a bit clearer if you created an extension (that implements IWorkflowInstanceExtension) to perform your action here.
For example:
public sealed class AsyncWorkExtension
: IWorkflowInstanceExtension
{
// only one extension per workflow
private WorkflowInstanceProxy _proxy;
private Bookmark _lastBookmark;
/// <summary>
/// Request the extension does some work for an activity
/// during which the activity will idle the workflow
/// </summary>
/// <param name="toResumeMe"></param>
public void DoWork(Bookmark toResumeMe)
{
_lastBookmark = toResumeMe;
// imagine I kick off some async op here
// when complete system calls WorkCompleted below
// NOTE: you CANNOT block here or you block the WF!
}
/// <summary>
/// Called by the system when long-running work is complete
/// </summary>
/// <param name="result"></param>
internal void WorkCompleted(object result)
{
//NOT good practice! example only
//this leaks resources search APM for details
_proxy.BeginResumeBookmark(_lastBookmark, result, null, null);
}
/// <summary>
/// When implemented, returns any additional extensions
/// the implementing class requires.
/// </summary>
/// <returns>
/// A collection of additional workflow extensions.
/// </returns>
IEnumerable<object> IWorkflowInstanceExtension
.GetAdditionalExtensions()
{
return new object[0];
}
/// <summary>
/// Sets the specified target
/// <see cref="WorkflowInstanceProxy"/>.
/// </summary>
/// <param name="instance">The target workflow instance to set.</param>
void IWorkflowInstanceExtension
.SetInstance(WorkflowInstanceProxy instance)
{
_proxy = instance;
}
}
Within the Activity, you'd use this thusly:
var ext = context.GetExtension<AsyncWorkExtension>();
var bookmark = context.CreateBookmark(BookmarkCallback);
ext.DoWork(bookmark);
return;
This way is much more explicit (instead of using the bookmark name to convey meaning to the "outside" world) and is much easier to extend if, say, you require to send out more information than a bookmark name.
Is there something actually resuming the bookmark here? If not the workflow will wait very patiently and nothing will happen.
Ok,
this question is for people with either a deep knowledge of PRISM or some magic skills I just lack (yet). The Background is simple: Prism allows the declaration of events to which the user can subscribe or publish. In code this looks like this:
_eventAggregator.GetEvent<LayoutChangedEvent>().Subscribe(UpdateUi, true);
_eventAggregator.GetEvent<LayoutChangedEvent>().Publish("Some argument");
Now this is nice, especially because these events are strongly typed, and the declaration is a piece of cake:
public class LayoutChangedEvent : CompositePresentationEvent<string>
{
}
But now comes the hard part: I want to trace events in some way. I had the idea to subscribe using a lambda expression calling a simple log message. Worked perfectly in WPF, but in Silverlight there is some method access error (took me some time to figure out the reason).. If you want to see for yourself, try this in Silverlight:
eA.GetEvent<VideoStartedEvent>().Subscribe(obj => TraceEvent(obj, "vSe", log));
If this would be possible, I would be happy, because I could easily trace all events using a single line to subscribe. But it does not... The alternative approach is writing a different functions for each event, and assign this function to the events. Why different functions? Well, I need to know WHICH event was published. If I use the same function for two different events I only get the payload as argument. I have now way to figure out which event caused the tracing message.
I tried:
using Reflection to get the causing event (not working)
using a constructor in the event to enable each event to trace itself (not allowed)
Any other ideas?
Chris
PS: Writing this text took me most likely longer than writing 20 functions for my 20 events, but I refuse to give up :-) I just had the idea to use postsharp, that would most likely work (although I am not sure, perhaps I end up having only information about the base class).. Tricky and so unimportant topic...
Probably the easiest thing would be to subclass CompositePresentationEvent and override the behavior of the Publish event. Here's the source for CompositePresentationEvent:
http://compositewpf.codeplex.com/SourceControl/changeset/view/26112#496659
Here's the current Publish behavior:
public virtual void Publish(TPayload payload)
{
base.InternalPublish(payload);
}
So you could just add a little to this:
public virtual override void Publish(TPayload payload)
{
ILoggerFacade logger = ServiceLocator.Current.GetInstance<ILoggerFacade>();
logger.Log("Publishing " + payload.ToString(), Category.Debug, Priority.Low);
base.InternalPublish(payload);
}
Here I'm using the logger facility built into Prism, but feel free to substitute your own (or better, just implement ILoggerFacade!).
I was surprised that there were any default messages being published or places to plug in tracing in this system... as much as EventAggregator is abused by people, you'd think this would be a big request!
A little late but better late than never! I recently had the same problem and this is how I solved it.
First, I didn't like the Prism method of publishing/subscribing to events, so I used a method like this instead:
http://neverindoubtnet.blogspot.com/2009/07/simplify-prism-event-aggregator.html
This post above suggests using Extension methods on Event Aggregator to simplify the call to publish/subscribe. As a result your client code looks like this:
IEventAggregator ev;
ev.Publish<MyCustomMessage>();
//or
ev.Publish(new MyCustomMessage(someData));
//and similarly subscription
ev.Subscribe<MyCustomMessage(this.OnCustomMessageReceived);
// ...
private void OnCustomMessageReceived(MyCustomMessage message)
{
// ...
}
// With a BaseMessageEvent class as follows (see the blog post above for where this comes from)
/// <summary>
/// Base class for all messages (events)
/// </summary>
/// <typeparam name="TMessage">The message type (payload delivered to subscribers)</typeparam>
public class BaseEventMessage<TMessage> : CompositePresentationEvent<TMessage>
{
}
Ok this is great, but rather than hacky extension methods I implemented my own event service as follows:
/// <summary>
/// The EventService instance
/// </summary>
public class EventService : IEventService
{
private readonly IEventAggregator eventAggregator;
private readonly ILoggerFacade logger;
/// <summary>
/// Initializes a new instance of the <see cref="EventService"/> class.
/// </summary>
/// <param name="logger">The logger instance.</param>
/// <param name="eventAggregator">The event aggregator instance.</param>
public EventService(IEventAggregator eventAggregator, ILoggerFacade logger)
{
this.logger = logger;
this.eventAggregator = eventAggregator;
}
#region IEventService Members
/// <summary>
/// Publishes the event of type TMessageType to all subscribers
/// </summary>
/// <typeparam name="TMessageType">The message type (Payload), must inherit CompositeEvent</typeparam>
public void Publish<TMessageType>() where TMessageType : BaseEventMessage<TMessageType>, new()
{
TMessageType message = Activator.CreateInstance<TMessageType>();
this.Publish(message);
}
/// <summary>
/// Publishes the event of type TMessageType to all subscribers
/// </summary>
/// <typeparam name="TMessageType">The message type (Payload), must inherit CompositeEvent</typeparam>
/// <param name="message">The message to publish</param>
public void Publish<TMessageType>(TMessageType message) where TMessageType : BaseEventMessage<TMessageType>, new()
{
// Here we can log our message publications
if (this.logger != null)
{
// logger.log etc..
}
this.eventAggregator.GetEvent<TMessageType>().Publish(message);
}
/// <summary>
/// Subscribes to the event of type TMessage
/// </summary>
/// <typeparam name="TMessageType">The message type (Payload), must inherit CompositeEvent</typeparam>
/// <param name="action">The action to execute when the event is raised</param>
public void Subscribe<TMessageType>(Action<TMessageType> action) where TMessageType : BaseEventMessage<TMessageType>, new()
{
// Here we can log our message publications
if (this.logger != null)
{
// logger.log etc..
}
this.eventAggregator.GetEvent<TMessageType>().Subscribe(action);
}
#endregion
}
Then I register IEventService/EventService as a singleton in the bootstrapper and forget about using the IEventAggregator, just use this (however if someone uses the IEventAggregator, its the same instance as that used by the EventService so will still work).
Finally, another trick to add is to use the Stack Frame to tell me where publications and subscriptions are coming from. Note this is a slow process (unwinding the stack frame) so use it sparingly. If you are
raising an event regularly then perhaps put a flag in your BaseEventMessage and check that to see whether to log publications for certain event types.
// Inside Publish method ... Log the subscription
if (this.logger != null)
{
Type messageType = typeof(TMessageType);
Type callingType = GetCallingType();
string methodName = GetCallingMethod().Name;
// Log the publication of this event
this.logger.Log(
string.Format("Event {0} was published by {1}.{2}()",
messageType.Name,
callingType.Name,
methodName),
Category.Debug,
Priority.Low));
}
// Additional methods to add to EventService to get the calling type/class
//
/// <summary>
/// Gets the Type that called the method or property where GetCallingType is called
/// </summary>
/// <returns>The class type that called</returns>
[MethodImplAttribute(MethodImplOptions.NoInlining)]
public static Type GetCallingType()
{
int skip = 2;
MethodBase method = new StackFrame(skip, false).GetMethod();
return method.DeclaringType;
}
/// <summary>
/// Gets the Method that called the method or property where GetCallingMethod is called
/// </summary>
/// <returns>The method type that was called</returns>
public static MethodBase GetCallingMethod()
{
return new StackFrame(2, false).GetMethod();
}
Note the above won't work in Silverlight (the use of the StackFrame), but the rest does. I've found this invaluable when debugging the multitude of events flying around a Prism app!