I have application for which I need to add additional hidden logging.
I have put prototype in way.
using System;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Start");
new DummyTest().Report();
Console.WriteLine("End");
Console.ReadKey();
}
}
public class DummyTest
{
public void Report()
{
var reporter = new Reporter();
Console.WriteLine("Reporting");
for (var i =0; i < 155; i++)
{
reporter.Process(i);
}
Console.WriteLine("Reporting end");
}
}
public class Reporter
{
// attach behavior here
public void Process(int requestId)
{
Console.WriteLine("Processing request: {0}" , requestId);
System.Threading.Thread.Sleep(100);
}
}
Now I have new project logger.dll that contains
using System;
namespace logger
{
public class Log
{
public Log()
{
Console.WriteLine("Line executed");
}
}
}
Now I would like to execute this method every time Main gets executed. This however cannot be referenced in any other way except only by referencing the dll.
=Update=
I do not mind to have reference to that dll. But in main code I cannot have any reference to Log. I thought about using reflection in order to make this work. The problem I am trying to solve first is how to attach that to the execution.
Why I cannot call logger from main?
This is supposed to be reporting on usage of the class, monitoring usage, in order to report on performance on bottle necks.
You could do something like this:
void Main()
{
System.Console.SetOut(new CustomTextWriter());
Console.WriteLine("test");
}
public class CustomTextWriter : TextWriter
{
private TextWriter _consoleOut = null;
private Log _logger = null;
public CustomTextWriter()
{
_consoleOut = System.Console.Out;
_logger = new Log();
}
public override void Write(char[] buffer, int index, int count)
{
this.Write(new String(buffer, index, count));
}
public override void Write(string value)
{
_consoleOut.Write(value);
_logger.Write(value);
}
public override void WriteLine(string value)
{
_consoleOut.WriteLine(value);
_logger.WriteLine(value);
}
public override Encoding Encoding
{
get { return System.Text.Encoding.Default; }
}
}
Wasn't sure if you wanted to do logging without actually calling Console.WriteLine() (if yes you'll need to look at Interception) but if that's ok then this should get you through.
Hope this helps.
You could do that with reflection like this:
// load the assembly
Assembly LogDll = Assembly.LoadFile(#"Log.dll");
// get the type of the Log class
Type LogType = LogDll.GetType("logger.Log");
// get instance of the Log class
object LogInstance = Activator.CreateInstance(LogType);
// invoke class member "Log()"
LogType.InvokeMember("Log",
BindingFlags.InvokeMethod |
BindingFlags.Instance |
BindingFlags.Public,
null,
LogInstance,
null);
Although I'm not sure if the constructor "Log()" already gets called by creating the instance. You should probably move your actual log method out of the constructor. To pass arguments you can use the last parameter of InvokeMember which is an array of the type Object.
Related
Is it possible to pass the generic type from one class to other class generic property.
For example:
Assembly Logger
namespace Logger
{
public class GenericLoger<T>
{
T _genericLog;
LogManager _logManager;
public GenericLoger(string logName)
{
_logManager = new LogManager(logName);
//Assigning the generic type to Log.GenerciLog, this is how I am
expecting or by some other possible way?.
Log.GenerciLog = _genericLog;
}
public static Write(string description)
{
_logManager.write(description);
}
}
public static class Log
{
LogManager _logManager;
static Log()
{
_logManager = new LogManager();
}
public static Write(string description)
{
_logManager.write(description);
}
//The generic type supplied in GenericLoger need to pass here,
//like this or by some other possible way?
public static T GenerciLog { get; internal set; }
//T is unrecognized here as type is available in GenericLoger
//I want to pass here from GenericLoger
}
}
Assembly Main Caller of Logger
using Logger;
namespace DataProcessor
{
internal class SpecialLogger
{
private static Lazy<GenericLog<SpecialLogger>> _passed;
public static GenericLog<SpecialLogger> Passed
{
get
{
if (_passed == null)
{
_passed = new Lazy<GenericLog<SpecialLogger>>(() => new GenericLog<SpecialLogger>("Passed"), true);
}
return _passed.Value;
}
}
private static Lazy<GenericLog<SpecialLogger>> _failed;
public static GenericLog<SpecialLogger> Failed
{
get
{
if (_failed == null)
{
_failed = new Lazy<GenericLog<SpecialLogger>>(() => new GenericLog<SpecialLogger>("Failed"), true);
}
return _failed.Value;
}
}
}
internal class Processor
{
public void ProcessRate()
{
var trans = dataManager.GetData();
//Will write the log in "Log.txt" file
Log.write(trans.Count + " transaction found");
foreach (var item in trans)
{
try
{
//transaction process code here
//This will write the text in "Passed.txt" file. 'Passed' property I want to access like this
Log.GenerciLog.Passed.Write(item);
}
catch (Exception ex)
{
//This will write the text in "Failed.txt" file. 'Failed' property I want to access like this
Log.GenerciLog.Failed.Write(item);
}
}
}
}
}
NOTE: In .NET you don't have a way for automatic type inference for use case like yours, also there is no automatic type substitution.
Not sure if this is what you are looking for
Your method definition should look like this
public static T GenerciLog<T> { get; internal set; }
and this is how to call it
try
{
//transaction process code here
//This will write the text in "Passed.txt" file. 'Passed' method I want to access like this
Log.GenerciLog<SpecialLogger>.Passed.Write(item);
}
catch (Exception ex)
{
//This will write the text in "Failed.txt" file. 'Failed' method I want to access like this
Log.GenerciLog<SpecialLogger>.Failed.Write(item);
}
This is a very simple log class. There is a lot more you could do with this sort of thing. Its all provided by log4net which I'd recommend using rather than trying to write your own logger. But the below is a start of how I'd implement a simple logger. It allows you to log to several different things at once. I appreciate the below doesn't answer exactly what you want but its an indication of how to start and you can adapt it to suit your needs.
public static class Logger
{
private static List<ILogger> _loggers = new List<ILogger>();
public static void Log(string message)
{
foreach (var logger in _loggers)
logger.Write(message);
}
public static void AddLogger(ILogger logger)
{
_loggers.Add(logger);
}
}
public interface ILogger
{
void Write(string message);
}
public class SpecialLogger : ILogger
{
public void Write(string message)
{
//special log code here eg
Console.WriteLine(message);
}
}
then somewhere do this
Logger.AddLogger(new SpecialLogger());
Logger.Log("A log message");
There is a webforms application with classes that contain lot of methods. I want to keep logs of the methods that are being called in a flexible and easy way.
I want to know which method has finally been called and some other additional info like:
input values and
result values
Crash exceptions (if there is a crash)
Currently, I am using log4net for filesystem logging like:
using log4net;
private static readonly ILog Log1 = LogManager.GetLogger("Log1");
public int DoSomething(int itemId = 0)
{
Log1.DebugFormat("[DoSomething] - Doing Something on item {0} Started", itemId );
try
{
//something..
}
catch (Exception ex)
{
Log1.Debug("[DoSomething] - Something Failed", ex);
}
Log1.DebugFormat("[DoSomething] - Doing Something on item {0} Finished", itemId );
return 0;
}
How is it possible to achieve this without writing every time these pieces of code in every method? Is there a better and automatic way?
What about the performance cost in every case?
An alternative approach would be great!
Below code should give you a starting point. It's a sample which uses console instead of log4net, but I think it's trivial to extend it to use whatever you need.
First install PostSharp nuget package. Then define new aspect:
[Serializable]
public sealed class TraceAttribute : OnMethodBoundaryAspect
{
private readonly string _argumentsFormat;
[NonSerialized]
private string _methodName;
public TraceAttribute() {
}
public TraceAttribute(string argumentsFormat) {
_argumentsFormat = argumentsFormat;
}
public override void RuntimeInitialize(MethodBase method) {
_methodName = method.Name;
}
public override void OnEntry(MethodExecutionArgs args) {
string msg = $"[{_methodName}]: entered";
if (!String.IsNullOrWhiteSpace(_argumentsFormat)) {
msg += String.Format(". Arguments:" + _argumentsFormat, args.Arguments.ToArray());
}
Console.WriteLine(msg);
}
// Invoked at runtime after the target method is invoked (in a finally block).
public override void OnExit(MethodExecutionArgs args) {
string msg = $"[{_methodName}]: exited";
if (!String.IsNullOrWhiteSpace(_argumentsFormat)) {
msg += String.Format(". Arguments: " + _argumentsFormat, args.Arguments.ToArray());
}
Console.WriteLine(msg);
}
public override void OnException(MethodExecutionArgs args) {
string msg = $"[{_methodName}]: exception";
if (!String.IsNullOrWhiteSpace(_argumentsFormat))
{
msg += String.Format(". Arguments: " + _argumentsFormat, args.Arguments.ToArray());
}
msg += ". Details: " + args.Exception.ToString();
Console.WriteLine(msg);
}
}
What we basically do here is inheriting MethodBoundaryAspect and define what code should be executed when target method is entered, exited, and when exception is thrown. Use it like this:
public class Program {
static void Main(string[] args) {
TestStuff(1);
TestStuff(2);
TestStuff(3);
Console.ReadKey();
}
[Trace("itemId: {0}")]
static void TestStuff(int itemId) {
Console.WriteLine("Inside TestStuff: " + itemId);
if (itemId == 3)
throw new Exception("Test exception");
}
}
You can also apply that attribute to whole classes. In this case - all methods inside that class will be traced.
I have an object that only initializes itself with barebones data when constructed (fast), and loads itself for real (slow) when first accessed. The idea is that I'm creating a lot of these barebones objects at startup and hash them into a map, then fully load each object whenever it is individually accessed for the first time. The problem is that I cannot guarantee how clients will interact with this object, there are multiple public methods that might be invoked.
Is there a good pattern to support this kind of situation? The obvious (and my current) solution is to track state with an internal bool, check against that bool in every function that might be invoked, and load that way. But that requires code duplication of that behavior across all public functions, and is vulnerable to errors.
I can imagine a single point-of-entry method that then dishes out behaviors based on a client request type etc., but before I go consider going down that road I want to see if there's a commonly accepted approach/pattern that I might not be aware of. I'm doing this in C#, but any insight is appreciated.
If I understood what you want to achieve, you are looking for the Proxy Design Pattern, more specifically, a virtual Proxy.
Refer to http://www.dofactory.com/net/proxy-design-pattern
A small example would be something like:
public abstract class IObjectProvider
{
public abstract IObjectProvider Object{get;}
public abstract void doStuff();
}
public class RealObject : IObjectProvider
{
public RealObject()
{
//Do very complicated and time taking stuff;
}
public override IObjectProvider Object
{
get { return this; }
}
public override void doStuff()
{
//do this stuff that these objects normally do
}
}
public class ObjectProxy : IObjectProvider
{
private IObjectProvider objectInstance = null;
public override IObjectProvider Object
{
get
{
if (objectInstance == null)
objectInstance = new RealObject();
return objectInstance;
}
}
public override void doStuff()
{
if(objectInstance!=null)
objectInstance.doStuff();
}
}
public class SkeletonClass
{
public IObjectProvider Proxy1 = new ObjectProxy();
public IObjectProvider Proxy2 = new ObjectProxy();
}
static void Main(String[] args)
{
//Objects Not Loaded
SkeletonClass skeleton = new SkeletonClass();
//Proxy1 loads object1 on demand
skeleton.Proxy1.Object.doStuff();
//Proxy2 not loaded object2 until someone needs it
}
Here's an example of dynamic proxy approach.
using System;
using System.Diagnostics;
using Castle.DynamicProxy; //Remember to include a reference, too. It's nugettable package is Castle.Core
namespace ConsoleApp
{
public class ActualClass
{
//Have static instances of two below for performance
private static ProxyGenerator pg = new ProxyGenerator();
private static ActualClassInterceptor interceptor = new ActualClassInterceptor();
//This is how we get ActualClass items that are wrapped in the Dynamic Proxy
public static ActualClass getActualClassInstance()
{
ActualClass instance = new ActualClass();
return pg.CreateClassProxyWithTarget<ActualClass>(instance, interceptor);
}
//Tracking whether init has been called
private bool initialized = false;
//Will be used as evidence of true initialization, i.e. no longer null
private int? someValue = null;
public void Initialize()
{
if (!initialized)
{
//do some initialization here.
someValue = -1; //Will only get set to non-null if we've run this line.
initialized = true;
}
}
//Any methods you want to intercept need to be virtual!
public virtual int replaceValue(int value)
{
//below will blow up, if someValue has not been set to -1 via Initialize();
int oldValue = someValue.Value;
someValue = value;
return oldValue;
}
//block off constructor from public to enforce use of getActualClassInstance
protected ActualClass() { }
}
public class ActualClassInterceptor : ActualClass, IInterceptor
{
public void Intercept(IInvocation invocation)
{
//Call initialize before proceeding to call the intercepted method
//Worth noting that this is the only place we actually call Initialize()
((ActualClass)invocation.InvocationTarget).Initialize();
invocation.Proceed();
}
}
class Program
{
static void Main(string[] args)
{
ActualClass instance1 = ActualClass.getActualClassInstance();
ActualClass instance2 = ActualClass.getActualClassInstance();
int x1 = instance1.replaceValue(41);
int x2 = instance2.replaceValue(42);
int y1 = instance1.replaceValue(82);
Debug.Assert(y1 == 41);
int y2 = instance2.replaceValue(84);
Debug.Assert(y2 == 42);
var read = Console.ReadKey();
}
}
}
How to avoid a pair of repetitive lines before and after invocations in sample below ?
Details: This is compileable mock of what is real larger code. Generally it is a layer of proxy classes containing service clients with variety of APIs. The repetitive part is pre- and post- invocation for every method of every client. Unfortunately there is no single signature for all possible methods, the pre- and post- parts need a pointer to client's channel and context.
Is it possible to apply something advanced like AOP, Generics, Delegates, Attributes etc. ? Thank you
using System;
namespace ConsoleApplication
{
class ClassServiceClient: IDisposable
{
public Object channel()
{
return "something";
}
public Object context()
{
return "something other";
}
}
class ClassA : ClassServiceClient
{
public Object methodA()
{
return "something other";
}
}
class ClassB : ClassServiceClient
{
public void methodB(string param)
{
return;
}
}
class ClassAProxy
{
public Object methodA()
{
using (ClassA client = new ClassA())
{
Program.preparation(client.channel()); //<---- repetitive part
Object result = client.methodA();
Program.postinvocation(client.context());//<---- repetitive part
return result;
}
}
}
class ClassBProxy
{
public void methodB(string param)
{
using (ClassB client = new ClassB())
{
Program.preparation(client.channel()); //<---- repetitive part
client.methodB(param);
Program.postinvocation(client.context());//<---- repetitive part
return;
}
}
}
class Program
{
public static void preparation(Object channel)
{
// Do something with channel
}
public static void postinvocation(Object context)
{
// Do something with context
}
static void Main(string[] args)
{
}
}
}
If you can use a common base class, you can easily use a public sealed method that does the invocation and a protected abstract method that does the logic, e.g.
class ProxyBase{
public void Method(params object[] args){
PreConditions();
Invoke(args);
PostConditions();
}
protected abstract void Invoke(object[] args);
}
class ClassAProxy{
protected override void Invoke(object[] args){
client.Method(args[0]);
}
}
You can achieve similar results functionally by declaring a InvocationHandler in your Program class that takes an action:
class Program{
public static void Invoke(object[] args, Action action){
PreConditions();
action();
PostConditions();
}
}
class ClassAProxy{
public void MethodA(int i){
Program.Invoke(() => client.Something(i));
}
}
I need to get MethodInfo for method called in Action delegate in order to check, whether methods called in Action has MyCustomAttibute
public void Foo( Action action )
{
if(Attribute.GetCustomAttributes(action.Method, typeof(MyCustomAttribute)).Count() == 0)
{
throw new ArgumentException("Invalid action");
}
}
The Foo method should be able to be called as following:
Foo(() =>
{
instanceOfFooClass.Method1().Method2();
});
In Foo method I want to be sure that Method1 and Method2 has MyCustomAttribute. However action.Method is giving me the MethodInfo, which is the action of delegate, which happens when using lambda expression. Is there any way to get Method1 and Method2 MethodInfo?
As mentioned in the comments, Expression<T> is probably the best way to achieve this. However, it requires a Compile() at runtime so it should be performance profiled.
With Expression<T> you can easily get access to Method info like this:
public MethodInfo GetMethodInfo(Expression<Action> action)
{
return ((MethodCallExpression)action.Body).Method;
}
But, before executing the action you must do this:
private void InvokeMethod(Expression<Action> action)
{
action.Compile().Invoke();
}
EDIT
Ah yes, I forgot how to get access to the customer attribute. You would do it like this:
var methodInfo = ((MethodCallExpression)myAction.Body).Method;
var attributes = methodInfo.GetCustomAttributes<T>(true);
EXAMPLE
Here is an example showing passing chained method calls to Expression<Action>:
public class ActionTest
{
public void DoAction(Action action)
{
action();
}
public void DoExpressionAction(Expression<Action> action)
{
var method2Info = ((MethodCallExpression)action.Body).Method;
// a little recursion needed here
var method1Info = ((MethodCallExpression)((MethodCallExpression)action.Body).Object).Method;
var myattributes2 = method2Info.GetCustomAttributes(typeof(MyAttribute), true);
var myattributes1 = method1Info.GetCustomAttributes(typeof(MyAttribute), true);
action.Compile().Invoke();
}
}
[AttributeUsage(AttributeTargets.Method)]
public class MyAttribute : Attribute
{
private string message;
public MyAttribute(string message)
{
this.message = message;
}
}
public class MethodTest
{
[MyAttribute("Number1")]
public MethodTest Method1()
{
Console.WriteLine("Action");
return this;
}
[MyAttribute("Number2")]
public MethodTest Method2()
{
Console.WriteLine("ExpressionAction");
return this;
}
}
class Program
{
static void Main(string[] args)
{
ActionTest target = new ActionTest();
MethodTest instance = new MethodTest();
target.DoExpressionAction(() => instance.Method1().Method2() );
Console.ReadLine();
}
static void Method1()
{
Console.WriteLine("Action");
}
static void Method2()
{
Console.WriteLine("ExpressionAction");
}
}
If you call your Foo() methdod like this:
Foo(instanceOfFooClass.Method);
Your code works as you'd expect (void methods are actions, after all).
On a side note, I think "chaining" method calls in fact counts as you're only passing the last one through.
Full sample demonstrating the behavior:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication4
{
class MyCustomAttribute : Attribute { }
class FooClass
{
[MyCustom]
public void DecoratedMethod() { Console.WriteLine("Decorated Method - executed."); }
public void NotDecoratedMethod() { Console.WriteLine("Not Decoreated Method - executed."); }
}
class Program
{
static void Main(string[] args)
{
FooClass instanceOfFooClass = new FooClass();
Foo(instanceOfFooClass.DecoratedMethod);
Foo(instanceOfFooClass.NotDecoratedMethod);
Console.ReadLine();
}
public static void Foo(Action action)
{
if (Attribute.GetCustomAttributes(action.Method, typeof(MyCustomAttribute)).Count() == 0)
Console.WriteLine(string.Format("Invalid method {0}", action.Method.Name));
else
{
Console.WriteLine(string.Format("Valid method {0}", action.Method.Name));
action.Invoke();
}
}
}
}