Testing private method calls - c#

Take this class:
public class LoginPresenter
{
private ILoginView view;
private APIWrapper api;
(...)
public virtual IEnumerator Login(string email, string password)
{
return api.Login(email, password, OnSuccess, OnError);
}
private void OnError(HttpError error)
{
switch (error.statusCode)
{
case 0:
view.ShowMessage("Check your Internet Connection");
break;
default:
view.ShowMessage("Invalid Credentials");
break;
}
}
(...)
}
I need to write a test for when Login fails, but I'm not sure about the right way to do it. This is how I was asked to do it:
public class LoginPresenterTests
{
private LoginPresenter presenter;
private ILoginView view;
(...)
[Test]
public void _03_Test_LoginOnError()
{
//Arrange
Dictionary<int, string> statusCodeMessages = new Dictionary<int, string>()
{
{0, "Check your Internet Connection"},
{401, "Invalid Credentials"}
};
//Act
foreach (var statusCodeMessage in statusCodeMessages)
{
object[] args = { new HttpError(statusCodeMessage.Key, "", "") };
ReflectionUtils.Invoke(presenter, "OnError", args);
//Assert
view.Received().ShowMessage(statusCodeMessage.Value);
}
}
(...)
}
But it seems so wrong to me. This is nothing but a mirror of the original function. A single change to the message string would break the test. Is this really what testing is about? Shouldn't I just be checking whether OnError is called if login fails, nothing more?
Then again, given that OnError is a callback and a private method, I don't know how to check if it was called...

You are right, it is generally not considered good practice to invoke private methods using reflection when testing.
For this answer, I will assume you are writing a unit test for LoginPresenter, and so you should not be concerned with the behaviour of ApiWrapper or the View. The approach would be different if you were writing an integration test.
I assume the ApiWrapper class is part of your codebase? (Sorry I'm not familiar with Unity). If so, you could create an interface for ApiWrapper, then have LoginPresenter reference the interface instead of the concrete class. The following technique may also be possible without the interface, as long as the Login method is virtual.
You're missing the part of the code where the view and api are instantiated or, more likely, injected into the presenter via the constructor. Ideally, the class looks like this:
public class LoginPresenter
{
private ILoginView view;
private IAPIWrapper api;
public LoginPresenter(ILoginView view, IAPIWrapper api)
{
this.api = api;
this.view = view;
}
public virtual IEnumerator Login(string email, string password)
{
return api.Login(email, password, OnSuccess, OnError);
}
// etc
Next, in your test, you can use a mocking framework (such as NSubstitute) to pass a mock of your api and view into the LoginPresenter. Then, you mock the api.Login method, and tell it to call its fourth argument (OnError) when it executes. How exactly you do this will depend on your mocking framework.
Finally, you assert that the view received the ShowMessage call, in the same way as you are doing already.

Related

How to use class Object in out parameter with Moq

I was trying to Mock some some functionality of my Services. The code goes like this.
public interface IObj {
public bool anotherMethod(string input, out string responseString);
}
public class SomeClass {
public bool SomeMethod(string input, out IObj outputObj) {
// some logic
if (logic is correct) {
outputObj = // object of IObj
return true;
}
outputObj = null;
return false;
}
}
public class Service {
public void executingMethod(){
if (this.someClassObj.SomeMethod(this.inputString, out outputObj) {
if (outputObj.anotherMethod(this.anotherInputString, out responseString)
{
// some business logic
}
}
}
}
Now i want to Mock the method executingMethod behaviour vai UnitTest using Moq and xUnit.
But while mocking I am getting issue with out parameter. In this way I am trying to mock the behaviour.
[Fact]
public void MockingMethod(){
// Arrange
Mock<SomeClass> mockSomeClass = new Mock<SomeClass>();
Mock<IObj> mockIObj = new Mock<IObj>();
string mockedResponse = "someResponse";
// here i am getting the issue, as out is expecting actual object not mocked object.
mockSomeClass.Setup(s => s.SomeMethod(It.IsAny<string>(), out mockIObj).Returns(true);
mockIObj.Setup(s => s.anotherMethod(It.IsAny<string(), out mockedResponse).Returns(true);
}
Any help will be much appreciated. TIA.
I tried to use as suggested by #Roman as well.
mockSomeClass.Setup(s => s.SomeMethod(It.IsAny<string>(), out mockIObj.Object).Returns(true);
but it is throwing this error -> "A property or indexer may not be passed as out or ref parameter"
Try “mockIObj.Object” . This should pass in the mocked object rather than the mocked instance
I Found other way to resolve this issue.
This method public bool SomeMethod(string input, out IObj outputObj)
was calling one another method like this public bool oneAnotherMethod(string input, out string outputResponse) mocking this method resolve the issue.
I was not knowing that mocking internal calls can propagate above the calling chain.
Thanks for all the help.

C# Use Generics to Call Overridden Method

I think I am a bit mixed up at this point, but I can't seem to be able to solve this issue.
I have an Interface ILinkHandler<T> and 4 other handler classes (inheriting from that interface) that validate different structures of links. From that interface, I have a Task<List<T>> Validate() function that does the validation of links and returns a Task> of results. Depending on T, I return a different model on Validate() (I have 4 different models).
My console app does the following. It calls the Task<List<T>> Validate(); method of every link type and creates some logs after getting results (note that Validate() is async). Every log is a little bit different, since the model is different, so I overrode a method named WriteResults(ModelX results, string name) and from the ModelX type (see end of question, I posted 2 examples), I do some stuff different (not important on this scope I think, but I can provide details if necessary). This method is NOT async.
I wanted to use Generics and my Interface to create a method (ValidateModel<T>) that handles the right call to the overridden method WriteResults from the type of the model and calls the Validate() method from the interface.
The code below is that I did that worked, but the if part resembles what I currently have in my main and I want to avoid.
public void ValidateModel<T>(ILinkHandler<T> handler, string name) where T : class
{
Console.WriteLine($"Validating {name}");
var results = handler.Validate();
if (typeof(T) == typeof(InternalLinksModel))
{
WriteResults(results.Result as List<InternalLinksModel>, name);
}
else // continue with other models
}
Here is what I have in my main:
private static void Main(string[] args)
{
Console.WriteLine("Validating External_Links");
var resultsForExternalLinks = ExternalLinkHandler.Validate();
WriteResults(resultsForExternalLinks.Result, "External_Links");
Console.WriteLine("Validating Image_Links");
var resultsForImageLinks = ImageLinkHandler.Validate();
WriteResults(resultsForImageLinks.Result, "Image_Links");
// and so on
}
I want more something like this if possible, but this does not compile:
public void ValidateModel<T>(ILinkHandler<T> handler, string name) where T : class
{
Console.WriteLine($"Validating {name}");
var results = handler.Validate();
WriteResults<T>(results.Result as List<T>, name);
}
Here is the definition of WriteResults (note that since it's overridden, I have 4 methods with their signature changing in the type of the list):
private void WriteResults(List<InternalLinksModel> results, string filename) { // Logs results into folder to display in jenkins }
private void WriteResults(List<PdfLinksModel> results, string filename) { // Logs results into folder to display in jenkins }
// and so on
EDIT: Adding more code
Interface:
public interface ILinkHandler<T>
{
Task<List<T>> Validate();
}
Example of Handler Class inheriting the interface:
public class InternalLinkHandler : ILinkHandler<InternalLinksModel>
{
public List<InternalLinksModel> InternalLinks = new List<InternalLinksModel>();
public async Task<List<InternalLinksModel>> Validate()
{
// Here set up my tests, call tasks that modifies InternalLinks List and I await for its results
return InternalLinks
}
Main Class (named XmlLinkCheckerValidator) where my code runs currently (and it works):
public class XmlLinkCheckerValidator
{
// References to all modes
public ExternalLinkHandler ExternalLinkHandler => new ExternalLinkHandler();
public ImageLinkHandler ImageLinkHandler => new ImageLinkHandler();
public InternalLinkHandler InternalLinkHandler => new InternalLinkHandler();
public PdfLinkHandler PdfLinkHandler => new PdfLinkHandler();
public void ValidateIPack()
{
InitialSetup();
Console.WriteLine("Validating External_Links");
var resultsForExternalLinks = ExternalLinkHandler.Validate();
WriteResultsForIPacksInCsv(resultsForExternalLinks.Result, "External_Links");
Console.WriteLine("Validating Image_Links");
var resultsForImageLinks = ImageLinkHandler.Validate();
WriteResultsForIPacksInCsv(resultsForImageLinks.Result, "Image_Links");
Console.WriteLine("Validating Internal_Links");
var resultsForInternalLinks = InternalLinkHandler.Validate();
WriteResultsForIPacksInCsv(resultsForInternalLinks.Result, "Internal_Links");
// Console.WriteLine("Validating Pdf Links");
// var results = XmlLinkExtractorFromIPacks.PdfLinkHandler.Validate();
// WriteResultsForIPacks(results, "Pdf Links");
}
private void WriteResultsForIPacksInCsv(List<InternalLinksModel> results, string filename) { logging results }
private void WriteResultsForIPacksInCsv(List<ExternalLinksModel> results, string filename) { logging results }
private void WriteResultsForIPacksInCsv(List<ImageLinksModel> results, string filename) { logging results }
private void WriteResultsForIPacksInCsv(List<PdfLinksModel> results, string filename) { logging results }
private void WriteResultsForIPacksInCsv(List<InternalLinksModel> results, string filename) { logging results }
I finally refactored all my code and it looks much clear. As I said, in the beginning, I think I got a bit mixed up and it all started from one bad design decision I took.
In short, I added a new method, WriteResults(string filename). Doing so, I implemented the method and removed the overridden method (WriteResultsForIPacksInCsv(List<WhateverModelIHad> results, string filename)) from my "Main" class. From that, I changed the Validate method signature in the interface to Task<List<PossibleResults>> Validate() and since every model has that in common, I removed the generic in the interface. I can now call my handlers the following way:
public void Validate(ILinkHandler handler, string filename)
{
Console.WriteLine($"Validating {filename}");
var results = handler.Validate();
SetUpResultsStatistics(results.Result, $"{filename}_Statistics");
handler.WriteResults(filename);
}
I created a function named void SetUpResultsStatistics(List<PossibleResults> results, string filename) which gives statistics of results and it is common to all handlers (thus, to avoid duplication I put it there).
Code is now much clearer and it now does not use any generics nor overridden method. I, however, am still curious as to how should I handle a case like that and will try to formulate it in another question with a much simpler example.
Thank you all for your comments, really appreciated!

How can this class be designed better?

We have a Web API library, that calls into a Business/Service library(where our business logic is located), which in turn calls a Data access library (Repository).
We use this type of data transfer object all over the place. It has a "Payers" property that we may have to filter (meaning, manipulate its value). I have gone about implementing that check as such, but it feels dirty to me, as I'm calling the same function all over the place. I have thought about either:
Using an attribute filter to handle this or
Making the RequestData a property on the class, and do the filtering in the constructor.
Any additional thoughts or design patterns where this could be designed more efficiently:
public class Example
{
private MyRepository _repo = new MyRepository();
private void FilterRequestData(RequestData data)
{
//will call into another class that may or may not alter RequestData.Payers
}
public List<ReturnData> GetMyDataExample1(RequestData data)
{
FilterRequestData(RequestData data);
return _repo.GetMyDataExample1(data);
}
public List<ReturnData> GetMyDataExample2(RequestData data)
{
FilterRequestData(RequestData data);
return _repo.GetMyDataExample2(data);
}
public List<ReturnData> GetMyDataExample3(RequestData data)
{
FilterRequestData(RequestData data);
return _repo.GetMyDataExample3(data);
}
}
public class RequestData
{
List<string> Payers {get;set;}
}
One way of dealing with repeated code like that is to use a strategy pattern with a Func (and potentially some generics depending on your specific case). You could refactor that into separate classes and everything but the basic idea looks like that:
public class MyRepository
{
internal List<ReturnData> GetMyDataExample1(RequestData arg) { return new List<ReturnData>(); }
internal List<ReturnData> GetMyDataExample2(RequestData arg) { return new List<ReturnData>(); }
internal List<ReturnData> GetMyDataExample3(RequestData arg) { return new List<ReturnData>(); }
}
public class ReturnData { }
public class Example
{
private MyRepository _repo = new MyRepository();
private List<ReturnData> FilterRequestDataAndExecute(RequestData data, Func<RequestData, List<ReturnData>> action)
{
// call into another class that may or may not alter RequestData.Payers
// and then execute the actual code, potentially with some standardized exception management around it
// or logging or anything else really that would otherwise be repeated
return action(data);
}
public List<ReturnData> GetMyDataExample1(RequestData data)
{
// call the shared filtering/logging/exception mgmt/whatever code and pass some additional code to execute
return FilterRequestDataAndExecute(data, _repo.GetMyDataExample1);
}
public List<ReturnData> GetMyDataExample2(RequestData data)
{
// call the shared filtering/logging/exception mgmt/whatever code and pass some additional code to execute
return FilterRequestDataAndExecute(data, _repo.GetMyDataExample2);
}
public List<ReturnData> GetMyDataExample3(RequestData data)
{
// call the shared filtering/logging/exception mgmt/whatever code and pass some additional code to execute
return FilterRequestDataAndExecute(data, _repo.GetMyDataExample3);
}
}
public class RequestData
{
List<string> Payers { get; set; }
}
This sort of thinking naturally leads to aspect oriented programming.
It's specifically designed to handle cross-cutting concerns (e.g. here, your filter function cuts across your query logic.)
As #dnickless suggests, you can do this in an ad-hoc way by refactoring your calls to remove the duplicated code.
More general solutions exist, such as PostSharp which give you a slightly cleaner way of structuring code along aspects. It is proprietary, but I believe the free tier gives enough to investigate an example like this. At the very least it's interesting to see how it would look in PostSharp, and whether you think it improves it at all! (It makes strong use of attributes, which extends first suggestion.)
(N.B. I'm not practically suggesting installing another library for a simple case like this, but highlighting how these types of problems might be examined in general.)

Design class chaining

I have a third party C# library for ldap operations. It does all operations on connection object as below:
LdapConnection connection = new LdapConnetion(Settings settings);
connection.Search(searchOU, filter,...);
which I feel is not readable. I want to write a wrapper around it so that I should be able to write code like below:
As I would like to have different Ldap classes like
public class AD: LdapServer { }
public class OpenLdap: LdapServer { }
and then
AD myldap = new AD(Settings settings);
myldap.Users.Search(searchOU, filter,...)
myldap.Users.Add(searchOU, filter,...)
myldap.Users.Delete(searchOU, filter,...)
I am thinking about Proxy design pattern, but things are not getting into my head about hot to go about it. What classes should I have etc.
Any help?
The solution posted above inherits from the LdapConnection. This is good if you want to maintain the inheritance chain, but I dont think that is necessary in your case. You simply want to customize and simplify the interface.
The proxy design pattern inherits from the underlying object so that the proxy object can be used anywhere that the underlying object is required, this is good if you want to "inject" extra functionality into the class without the clients of that class realising. I dont think this is your intention here?
The big problem with the solution posted above is that (because it inherits directly from LdapConnection) you can call search in two ways like so:
Settings settings = new Settings();
AD myAD = new AD(settings);
object results = myAD.Users.Search();
// OR
object results2 = myAD.Search();
As I'm sure you can see from the code, both of these call the exact same underlying method. But in my opinion, this is even more confusing to developers than just using the vanilla LdapConnection object. I would always be thinking "whats the difference between these seemingly identical methods??" Even worse, if you add some custom code inside the UsersWrapper Search method, you cannot always guarentee that it will be called. The possibility will always exist for a developer to call Search directly without going through the UsersWrapper.
Fowler in his book PoEAA defines a pattern called Gateway. This is a way to simplify and customize the interface to an external system or library.
public class AD
{
private LdapConnection ldapConn;
private UsersWrapper users;
public AD()
{
this.ldapConn = new LdapConnection(new Settings(/* configure settings here*/));
this.users = new UsersWrapper(this.ldapConn);
}
public UsersWrapper Users
{
get
{
return this.users;
}
}
public class UsersWrapper
{
private LdapConnection ldapConn;
public UsersWrapper(LdapConnection ldapConn)
{
this.ldapConn = ldapConn;
}
public object Search()
{
return this.ldapConn.Search();
}
public void Add(object something)
{
this.ldapConn.Add(something);
}
public void Delete(object something)
{
this.ldapConn.Delete(something);
}
}
}
This can then be used like so:
AD myAD = new AD();
object results = myAD.Users.Search();
Here you can see that the LdapConnection object is completly encapsulated inside the class and there is only one way to call each method. Even better, the setting up of the LdapConnection is also completely encapsulated. The code using this class doesn't have to worry about how to set it up. The settings are only defined in one place (in this class, instead of spread throughout your application).
The only disadvantage is that you loose the inheritance chain back to LdapConnection, but I dont think this is necessary in your case.
Ok, if you simply want to split the methods up into they objects that they act on (i.e. in your example add the .Users. before the method call) you can do something similar to this.. You'll need to get the method parameters and return types correct for your library, I've just used object here.
Is this the sort of thing you're looking for?
public class AD : LdapConnection
{
private UsersWrapper users;
public AD(Settings settings) : base(settings)
{
this.users = new UsersWrapper(this);
}
public UsersWrapper Users
{
get
{
return this.users;
}
}
public class UsersWrapper
{
private AD parent;
public UsersWrapper(AD parent)
{
this.parent = parent;
}
public object Search()
{
return this.parent.Search();
}
public void Add(object something)
{
this.parent.Add(something);
}
public void Delete(object something)
{
this.parent.Delete(something);
}
}
}
This can then be be used as follows:
Settings settings = new Settings();
AD myAD = new AD(settings);
object results = myAD.Users.Search();
Remember that this isn't strictly a "wrapper" because it actually inherits from the underlying class.

How do I intercept a method call in C#?

For a given class I would like to have tracing functionality i.e. I would like to log every method call (method signature and actual parameter values) and every method exit (just the method signature).
How do I accomplish this assuming that:
I don't want to use any 3rd party
AOP libraries for C#,
I don't want to add duplicate code to all the methods that I want to trace,
I don't want to change the public API of the class - users of the class should be able to call all the methods in exactly the same way.
To make the question more concrete let's assume there are 3 classes:
public class Caller
{
public static void Call()
{
Traced traced = new Traced();
traced.Method1();
traced.Method2();
}
}
public class Traced
{
public void Method1(String name, Int32 value) { }
public void Method2(Object object) { }
}
public class Logger
{
public static void LogStart(MethodInfo method, Object[] parameterValues);
public static void LogEnd(MethodInfo method);
}
How do I invoke Logger.LogStart and Logger.LogEnd for every call to Method1 and Method2 without modifying the Caller.Call method and without adding the calls explicitly to Traced.Method1 and Traced.Method2?
Edit: What would be the solution if I'm allowed to slightly change the Call method?
C# is not an AOP oriented language. It has some AOP features and you can emulate some others but making AOP with C# is painful.
I looked up for ways to do exactly what you wanted to do and I found no easy way to do it.
As I understand it, this is what you want to do:
[Log()]
public void Method1(String name, Int32 value);
and in order to do that you have two main options
Inherit your class from MarshalByRefObject or ContextBoundObject and define an attribute which inherits from IMessageSink. This article has a good example. You have to consider nontheless that using a MarshalByRefObject the performance will go down like hell, and I mean it, I'm talking about a 10x performance lost so think carefully before trying that.
The other option is to inject code directly. In runtime, meaning you'll have to use reflection to "read" every class, get its attributes and inject the appropiate call (and for that matter I think you couldn't use the Reflection.Emit method as I think Reflection.Emit wouldn't allow you to insert new code inside an already existing method). At design time this will mean creating an extension to the CLR compiler which I have honestly no idea on how it's done.
The final option is using an IoC framework. Maybe it's not the perfect solution as most IoC frameworks works by defining entry points which allow methods to be hooked but, depending on what you want to achive, that might be a fair aproximation.
The simplest way to achieve that is probably to use PostSharp. It injects code inside your methods based on the attributes that you apply to it. It allows you to do exactly what you want.
Another option is to use the profiling API to inject code inside the method, but that is really hardcore.
You could achieve it with Interception feature of a DI container such as Castle Windsor. Indeed, it is possible to configure the container in such way that every classes that have a method decorated by a specific attribute would be intercepted.
Regarding point #3, OP asked for a solution without AOP framework. I assumed in the following answer that what should be avoided were Aspect, JointPoint, PointCut, etc. According to Interception documentation from CastleWindsor, none of those are required to accomplish what is asked.
Configure generic registration of an Interceptor, based on the presence of an attribute:
public class RequireInterception : IContributeComponentModelConstruction
{
public void ProcessModel(IKernel kernel, ComponentModel model)
{
if (HasAMethodDecoratedByLoggingAttribute(model.Implementation))
{
model.Interceptors.Add(new InterceptorReference(typeof(ConsoleLoggingInterceptor)));
model.Interceptors.Add(new InterceptorReference(typeof(NLogInterceptor)));
}
}
private bool HasAMethodDecoratedByLoggingAttribute(Type implementation)
{
foreach (var memberInfo in implementation.GetMembers())
{
var attribute = memberInfo.GetCustomAttributes(typeof(LogAttribute)).FirstOrDefault() as LogAttribute;
if (attribute != null)
{
return true;
}
}
return false;
}
}
Add the created IContributeComponentModelConstruction to container
container.Kernel.ComponentModelBuilder.AddContributor(new RequireInterception());
And you can do whatever you want in the interceptor itself
public class ConsoleLoggingInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
Console.Writeline("Log before executing");
invocation.Proceed();
Console.Writeline("Log after executing");
}
}
Add the logging attribute to your method to log
public class Traced
{
[Log]
public void Method1(String name, Int32 value) { }
[Log]
public void Method2(Object object) { }
}
Note that some handling of the attribute will be required if only some method of a class needs to be intercepted. By default, all public methods will be intercepted.
If you write a class - call it Tracing - that implements the IDisposable interface, you could wrap all method bodies in a
Using( Tracing tracing = new Tracing() ){ ... method body ...}
In the Tracing class you could the handle the logic of the traces in the constructor/Dispose method, respectively, in the Tracing class to keep track of the entering and exiting of the methods. Such that:
public class Traced
{
public void Method1(String name, Int32 value) {
using(Tracing tracer = new Tracing())
{
[... method body ...]
}
}
public void Method2(Object object) {
using(Tracing tracer = new Tracing())
{
[... method body ...]
}
}
}
If you want to trace after your methods without limitation (no code adaptation, no AOP Framework, no duplicate code), let me tell you, you need some magic...
Seriously, I resolved it to implement an AOP Framework working at runtime.
You can find here : NConcern .NET AOP Framework
I decided to create this AOP Framework to give a respond to this kind of needs. it is a simple library very lightweight. You can see an example of logger in home page.
If you don't want to use a 3rd party assembly, you can browse the code source (open source) and copy both files Aspect.Directory.cs and Aspect.Directory.Entry.cs to adapted as your wishes. Theses classes allow to replace your methods at runtime. I would just ask you to respect the license.
I hope you will find what you need or to convince you to finally use an AOP Framework.
Take a look at this - Pretty heavy stuff..
http://msdn.microsoft.com/en-us/magazine/cc164165.aspx
Essential .net - don box had a chapter on what you need called Interception.
I scraped some of it here (Sorry about the font colors - I had a dark theme back then...)
http://madcoderspeak.blogspot.com/2005/09/essential-interception-using-contexts.html
I have found a different way which may be easier...
Declare a Method InvokeMethod
[WebMethod]
public object InvokeMethod(string methodName, Dictionary<string, object> methodArguments)
{
try
{
string lowerMethodName = '_' + methodName.ToLowerInvariant();
List<object> tempParams = new List<object>();
foreach (MethodInfo methodInfo in serviceMethods.Where(methodInfo => methodInfo.Name.ToLowerInvariant() == lowerMethodName))
{
ParameterInfo[] parameters = methodInfo.GetParameters();
if (parameters.Length != methodArguments.Count()) continue;
else foreach (ParameterInfo parameter in parameters)
{
object argument = null;
if (methodArguments.TryGetValue(parameter.Name, out argument))
{
if (parameter.ParameterType.IsValueType)
{
System.ComponentModel.TypeConverter tc = System.ComponentModel.TypeDescriptor.GetConverter(parameter.ParameterType);
argument = tc.ConvertFrom(argument);
}
tempParams.Insert(parameter.Position, argument);
}
else goto ContinueLoop;
}
foreach (object attribute in methodInfo.GetCustomAttributes(true))
{
if (attribute is YourAttributeClass)
{
RequiresPermissionAttribute attrib = attribute as YourAttributeClass;
YourAttributeClass.YourMethod();//Mine throws an ex
}
}
return methodInfo.Invoke(this, tempParams.ToArray());
ContinueLoop:
continue;
}
return null;
}
catch
{
throw;
}
}
I then define my methods like so
[WebMethod]
public void BroadcastMessage(string Message)
{
//MessageBus.GetInstance().SendAll("<span class='system'>Web Service Broadcast: <b>" + Message + "</b></span>");
//return;
InvokeMethod("BroadcastMessage", new Dictionary<string, object>() { {"Message", Message} });
}
[RequiresPermission("editUser")]
void _BroadcastMessage(string Message)
{
MessageBus.GetInstance().SendAll("<span class='system'>Web Service Broadcast: <b>" + Message + "</b></span>");
return;
}
Now I can have the check at run time without the dependency injection...
No gotchas in site :)
Hopefully you will agree that this is less weight then a AOP Framework or deriving from MarshalByRefObject or using remoting or proxy classes.
First you have to modify your class to implement an interface (rather than implementing the MarshalByRefObject).
interface ITraced {
void Method1();
void Method2()
}
class Traced: ITraced { .... }
Next you need a generic wrapper object based on RealProxy to decorate any interface to allow intercepting any call to the decorated object.
class MethodLogInterceptor: RealProxy
{
public MethodLogInterceptor(Type interfaceType, object decorated)
: base(interfaceType)
{
_decorated = decorated;
}
public override IMessage Invoke(IMessage msg)
{
var methodCall = msg as IMethodCallMessage;
var methodInfo = methodCall.MethodBase;
Console.WriteLine("Precall " + methodInfo.Name);
var result = methodInfo.Invoke(_decorated, methodCall.InArgs);
Console.WriteLine("Postcall " + methodInfo.Name);
return new ReturnMessage(result, null, 0,
methodCall.LogicalCallContext, methodCall);
}
}
Now we are ready to intercept calls to Method1 and Method2 of ITraced
public class Caller
{
public static void Call()
{
ITraced traced = (ITraced)new MethodLogInterceptor(typeof(ITraced), new Traced()).GetTransparentProxy();
traced.Method1();
traced.Method2();
}
}
You can use open source framework CInject on CodePlex. You can write minimal code to create an Injector and get it to intercept any code quickly with CInject. Plus, since this is Open Source you can extend this as well.
Or you can follow the steps mentioned on this article on Intercepting Method Calls using IL and create your own interceptor using Reflection.Emit classes in C#.
I don't know a solution but my approach would be as follows.
Decorate the class (or its methods) with a custom attribute. Somewhere else in the program, let an initialization function reflect all types, read the methods decorated with the attributes and inject some IL code into the method. It might actually be more practical to replace the method by a stub that calls LogStart, the actual method and then LogEnd. Additionally, I don't know if you can change methods using reflection so it might be more practical to replace the whole type.
You could potentially use the GOF Decorator Pattern, and 'decorate' all classes that need tracing.
It's probably only really practical with an IOC container (but as pointer out earlier you may want to consider method interception if you're going to go down the IOC path).
you need to bug Ayende for an answer on how he did it:
http://ayende.com/Blog/archive/2009/11/19/can-you-hack-this-out.aspx
AOP is a must for clean code implementing, however if you want to surround a block in C#, generic methods have relatively easier usage. (with intelli sense and strongly typed code) Certainly, it can NOT be an alternative for AOP.
Although PostSHarp have little buggy issues (i do not feel confident for using at production), it is a good stuff.
Generic wrapper class,
public class Wrapper
{
public static Exception TryCatch(Action actionToWrap, Action<Exception> exceptionHandler = null)
{
Exception retval = null;
try
{
actionToWrap();
}
catch (Exception exception)
{
retval = exception;
if (exceptionHandler != null)
{
exceptionHandler(retval);
}
}
return retval;
}
public static Exception LogOnError(Action actionToWrap, string errorMessage = "", Action<Exception> afterExceptionHandled = null)
{
return Wrapper.TryCatch(actionToWrap, (e) =>
{
if (afterExceptionHandled != null)
{
afterExceptionHandled(e);
}
});
}
}
usage could be like this (with intelli sense of course)
var exception = Wrapper.LogOnError(() =>
{
MessageBox.Show("test");
throw new Exception("test");
}, "Hata");
Maybe it's to late for this answer but here it goes.
What you are looking to achieve is built in MediatR library.
This is my RequestLoggerBehaviour which intercepts all calls to my business layer.
namespace SmartWay.Application.Behaviours
{
public class RequestLoggerBehaviour<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
{
private readonly ILogger _logger;
private readonly IAppSession _appSession;
private readonly ICreateLogGrain _createLogGrain;
public RequestLoggerBehaviour(ILogger<TRequest> logger, IAppSession appSession, IClusterClient clusterClient)
{
_logger = logger;
_appSession = appSession;
_createLogGrain = clusterClient.GetGrain<ICreateLogGrain>(Guid.NewGuid());
}
public async Task<TResponse> Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate<TResponse> next)
{
var name = typeof(TRequest).Name;
_logger.LogInformation($"SmartWay request started: ClientId: {_appSession.ClientId} UserId: {_appSession.UserId} Operation: {name} Request: {request}");
var response = await next();
_logger.LogInformation($"SmartWay request ended: ClientId: {_appSession.ClientId} UserId: {_appSession.UserId} Operation: {name} Request: {request}");
return response;
}
}
}
You can also create performance behaviours to trace methods that take too long to execute for example.
Having clean architecture (MediatR) on your business layer will allow you to keep your code clean while you enforce SOLID principles.
You can see how it works here:
https://youtu.be/5OtUm1BLmG0?t=1
Write your own AOP library.
Use reflection to generate a logging proxy over your instances (not sure if you can do it without changing some part of your existing code).
Rewrite the assembly and inject your logging code (basically the same as 1).
Host the CLR and add logging at this level (i think this is the hardest solution to implement, not sure if you have the required hooks in the CLR though).
The best you can do before C# 6 with 'nameof' released is to use slow StackTrace and linq Expressions.
E.g. for such method
public void MyMethod(int age, string name)
{
log.DebugTrace(() => age, () => name);
//do your stuff
}
Such line may be produces in your log file
Method 'MyMethod' parameters age: 20 name: Mike
Here is the implementation:
//TODO: replace with 'nameof' in C# 6
public static void DebugTrace(this ILog log, params Expression<Func<object>>[] args)
{
#if DEBUG
var method = (new StackTrace()).GetFrame(1).GetMethod();
var parameters = new List<string>();
foreach(var arg in args)
{
MemberExpression memberExpression = null;
if (arg.Body is MemberExpression)
memberExpression = (MemberExpression)arg.Body;
if (arg.Body is UnaryExpression && ((UnaryExpression)arg.Body).Operand is MemberExpression)
memberExpression = (MemberExpression)((UnaryExpression)arg.Body).Operand;
parameters.Add(memberExpression == null ? "NA" : memberExpression.Member.Name + ": " + arg.Compile().DynamicInvoke().ToString());
}
log.Debug(string.Format("Method '{0}' parameters {1}", method.Name, string.Join(" ", parameters)));
#endif
}

Categories

Resources