I've got a (prototype) class owned by the Spring.NET context, created with an AutoProxy with runtime constructor arguments. It get's instantiated like this.
var context = ContextRegistry.GetContext();
var myClass = context.GetObject("myclass", new object[]{ myRuntimeConstructorArgument }) as MyClass;
This class has some inner logic going, where it catches an event that gets handled by a class method, like this:
// MyClass owned by Spring.NET context
public class MyClass {
// InnerObject not owned by Spring context
private InnerObject innerobject;
// argument object not owned by Spring context
public MyClass(ObjectNotOwnedBySpring myRuntimeConstructorArgument) {
...
this.innerobject = new InnerObject();
this.innerobject.SomeEvent += this.handleSomeEvent;
}
// I would like to intercept this event handler
public virtual void handleMyEvent (object sender, EventArgs args)
{
// do stuff
}
}
I'm trying to use AOP to remove an abstraction leak (caused by a bug in an external component), by intercepting the handleMyEvent method. Because Spring.Aop uses a proxy based approach to intercept method calls, inner method calls don't get intercepted. I get that part.
If I understand the documentation correctly, that's where the InheritanceBasedAopConfigurer comes into play, by using a 'true' inheritance based AOP mechanism. From the documentation:
Interception advice is added directly in the method body before invoking the base class method.
Exactly what I need!
Unfortunatly, I can't get the InheritanceBasedAopConfigurer get to play nicely with the runtime constructor arguments:
Spring.Objects.Factory.ObjectCreationException: Error creating object with name 'myclass' > defined in 'file [spring-aop-config.xml] line 36' : Could not resolve matching constructor.
Is runtime constructor arguments not supported by the InheritanceBasedAopConfigurer ? Or is this a wrong use case for the InheritanceBasedAopConfigurer ?
Related
Today I stumbled upon a problem, which I couldn't explain to myself. I was trying to build a "generic handler builder", to clean up repetitive code in my project. I thought this could be easily achieved with some generics and the power of Action<T>.
I came up with a similar solution like this (this is a simplified version to show the "problem"):
using System;
namespace GenericActionBuilder {
public class FirstMessage { }
public class MessageHandler {
public void HandleMessage(object msg)
=> Console.WriteLine("Fallback object handler");
public void HandleMessage(FirstMessage msg)
=> Console.WriteLine("FirstMessage handler");
}
class Program
{
public static Action<MessageType> BuildHandler<MessageType>() {
Action<MessageType> handler = (msg) => {
Console.WriteLine($"Called with Type={msg.GetType().Name}");
var messageHandler = new MessageHandler();
messageHandler.HandleMessage(msg);
};
return handler;
}
static void Main(string[] args)
{
// This is the surprise
var generatedHandler = BuildHandler<FirstMessage>();
var msg = new FirstMessage();
Console.WriteLine($"Calling generated handler with type={msg.GetType().Name}");
generatedHandler(msg);
// This gives the expected behavior
var myHandler = new MessageHandler();
myHandler.HandleMessage(msg);
}
}
}
Output:
Calling generated handler with type=FirstMessage
Called with Type=FirstMessage
Fallback object handler
FirstMessage handler
Of course I would expect that, when I call HandleMessage with a FirstMessage object at hand, C# would pick the best matching overload: HandleMessage(FirstMessage). This is what happens if you don't utilize the "generic handler builder".
And even inside the generated handler the type of the msg is still FirstMessage. But still the call handler.HandleMessage(msg) triggers the "fallback" method with the object signature.
Can anybody explain this to me?
C# would pick the best matching overload
Yes, but it will do it on compile time (not runtime) based on information about type, which C# compiler can obtain from code.
Your handler has a generic parameter, but this parameter is not limited by any condition, so, it can be any type: FirstMessage, object or even Program and etc, then knowing this, the compiler will select "the best matching overload", which obviously is HandleMessage(object) because it can accept any provided type. To quickly check it, you can create base class/interface (Message) for messages and limit generic parameter to something like: where MessageType : Message and provide appropriate methods in MessageHandler class and you will see that the compiler will select HandleMessage(Message) instead of HandleMessage(object).
So, you can try to implement visitor (double dispatch) pattern to solve this problem (I assume that you have more message types).
Consider following code:
public class Test
{
[System.AttributeUsage(System.AttributeTargets.Method)]
class MethodAttribute : System.Attribute
{
public MethodAttribute(System.Reflection.MethodInfo methodInfo)
{
}
}
public void Foo()
{
}
[Method(Test.Foo)] //< THIS IS THE IMPORTANT LINE
public void Boo()
{
}
}
I want to store MethodInfo instance of Foo in attribute of Boo, but problem is, that I cannot use Foo nor Test.Foo to get instance of MethodInfo. I can NOT use typeof(Test).GetMethod("Foo") (not my decision).
Important information:
Generated error is: error CS0120: An object reference is required to access non-static member `Test.Foo()'
I'm coding in Unity3D which is using Mono, not .Net. (more info http://docs.unity3d.com/410/Documentation/ScriptReference/MonoCompatibility.html )
Windows 7
Absolutely unimportant information:
Why I cannot use typeof(Test).GetMethod("Foo"): I'm not allowed. It's not in my power to change this decision. I can not. (Also, personally, I would like to avoid it anyway as it needs to do some lookup instead of getting statically the data. Also it won't be changed automatically during refactoring and will be checking run-time, not compile-time.)
Why I want to do this: later in code, I want to create a delegate of Boo() (this time normally, with an instance) and use in special even system or something. Before it's called, this attribute allows to setup method to be called in prepare for main event (it's optional, it can be null) and I know how to create a delegate when I have an object and a method info.
Why I cannot just provide both delegates when registering or something: because class containing these methods is not always the one who registers to event source, I need to keep the registration code as simple as possible. In other words, I want to avoid situation when person writing method responsible for connecting forgots to add this preparation delegate.
use expression :
static public class Metadata<T>
{
static public PropertyInfo Property<TProperty>(Expression<Func<T, TProperty>> property)
{
var expression = property.Body as MemberExpression;
return expression.Member as PropertyInfo;
}
}
var foo = Metadata<Test>.Property(test => test.Foo);
IModificationRequst<Employee> req = new ModificationRequst();
Locator.Instance.GetService<IModificationRequstHandler<Employee>>().Handle(req);
I have a service locator that locates services that returns instances of objects implementing IModificationRequstHandler.
I am trying to modify it to rather than returning a IModificationRequstHandler implementer, it is just internally finds the service and invokes it's handler method, so the above 2 lines would look like this instead:
IModificationRequst<Employee> req = new ModificationRequst();
Locator.Instance.HandleRequest<IModificationRequst<Employee>>(req);
But having hard time with the generics, is there an already established pattern for resovling the requests to their proper request handlers and invoking their handling, rather than getting a handler and then invoking their Handle method from the client?
That violates Single Responsibility Principle. You should not make the service locator implement logic for different services.
If you do want to use static classes you should add another one:
public static class RequestHandler
{
public static void Handle<T>(T request)
{
Locator.Instance.GetService<IModificationRequstHandler<T>>().Handle(req);
}
}
And then:
IModificationRequst<Employee> req = new ModificationRequst();
RequestHandler.Handle(req);
(Sidenote: You might look up Dependency Injection & IoC containers since it makes the code more maintainable)
Your HandleRequest method in the locator class should be defined as follows (assuming Handle has a return type of void):
public void HandleRequest<T>(IModificationRequest<T> req)
{
IModificationRequstHandler<T> handler = GetService<IModificationRequest<T>>();
handler.Handle(req);
}
and your IModificationRequstHandler interface should be defined as follows:
public interface IModificationRequstHandler<T>
{
void Handle(IModificationRequst<T> req);
}
and your call will then become:
Locator.Instance.HandleRequest(req);
The generic type parameter Employee here is inferred from the parameter value req and thus does not need to be specified.
I currently have 2 concrete methods in 2 abstract classes. One class contains the current method, while the other contains the legacy method. E.g.
// Class #1
public abstract class ClassCurrent<T> : BaseClass<T> where T : BaseNode, new()
{
public List<T> GetAllRootNodes(int i)
{
//some code
}
}
// Class #2
public abstract class MyClassLegacy<T> : BaseClass<T> where T : BaseNode, new()
{
public List<T> GetAllLeafNodes(int j)
{
//some code
}
}
I want the corresponding method to run in their relative scenarios in the app. I'm planning to write a delegate to handle this. The idea is that I can just call the delegate and write logic in it to handle which method to call depending on which class/project it is called from (at least thats what I think delegates are for and how they are used).
However, I have some questions on that topic (after some googling):
1) Is it possible to have a delegate that knows the 2 (or more) methods that reside in different classes?
2) Is it possible to make a delegate that spawns off abstract classes (like from the above code)? (My guess is a no, since delegates create concrete implementation of the passed-in classes)
3) I tried to write a delegate for the above code. But I'm being technically challenged:
public delegate List<BaseNode> GetAllNodesDelegate(int k);
GetAllNodesDelegate del = new GetAllNodesDelegate(ClassCurrent<BaseNode>.GetAllRootNodes);
I got the following error:
An object reference is required for the non-static field, method, property ClassCurrent<BaseNode>.GetAllRootNodes(int)
I might have misunderstood something... but if I have to manually declare a delegate at the calling class, AND to pass in the function manually as above, then I'm starting to question whether delegate is a good way to handle my problem.
Thanks.
The way you're attempting to use delegates (constructing them with new, declaring a named delegate type) suggests that you're using C# 1. If you're actually using C# 3, it's much easier than that.
Firstly, your delegate type:
public delegate List<BaseNode> GetAllNodesDelegate(int k);
Already exists. It's just:
Func<int, List<BaseNode>>
So you don't need to declare your own version of it.
Secondly, you should think of a delegate as being like an interface with only one method in it, and you can "implement" it on the fly, without having to write a named class. Just write a lambda, or assign a method name directly.
Func<int, List<BaseNode>> getNodesFromInt;
// just assign a compatible method directly
getNodesFromInt = DoSomethingWithArgAndReturnList;
// or bind extra arguments to an incompatible method:
getNodesFromInt = arg => MakeList(arg, "anotherArgument");
// or write the whole thing specially:
getNodesFromInt = arg =>
{
var result = new List<BaseNode>();
result.Add(new BaseNode());
return result;
};
A lambda is of the form (arguments) => { body; }. The arguments are comma-separated. If there's only one, you can omit the parentheses. If it takes no parameters, put a pair of empty parentheses: (). If the body is only one statement long, you can omit the braces. If it's just a single expression, you can omit the braces and the return keyword. In the body, you can refer to practically any variables and methods from the enclosing scope (apart from ref/out parameters to the enclosing method).
There's almost never any need to use new to create a delegate instance. And rarely a need to declare custom delegate types. Use Func for delegates that return a value and Action for delegates that return void.
Whenever the thing you need to pass around is like an object with one method (whether an interface or a class), then use a delegate instead, and you'll be able to avoid a lot of mess.
In particular, avoid defining interfaces with one method. It will just mean that instead of being able to write a lambda to implement that method, you'll have to declare a separate named class for each different implementation, with the pattern:
class Impl : IOneMethod
{
// a bunch of fields
public Impl(a bunch of parameters)
{
// assign all the parameters to their fields
}
public void TheOneMethod()
{
// make use of the fields
}
}
A lambda effectively does all that for you, eliminating such mechanical patterns from your code. You just say:
() => /* same code as in TheOneMethod */
It also has the advantage that you can update variables in the enclosing scope, because you can refer directly to them (instead of working with values copied into fields of a class). Sometimes this can be a disadvantage, if you don't want to modify the values.
You can have a delegate that is initialized with references to different methods depending on some conditions.
Regarding your questions:
1) I'm not sure what you mean under "knows". You can pass any method to the delegate, so if you can write method that "knows" about some other methods than you can do a similar delegate.
2) Again, delegates can be created from any method that can be executed. For example if you have an initialized local variable of type ClassCurrent<T> you can created delegate for any instance method of type ClassCurrent<T>.
3) Delegate can call only the method that actually can be called. I mean that you cannot call ClassCurrent.GetAllRootNodes because GetAllRootNodes is not a static method, so you need an instance of the ClassCurrent to call it.
The delegate can stay in any class that has access to the ClassCurrent and MyClassLegacy.
For example you can create smth like:
class SomeActionAccessor<T>
{
// Declare delegate and fied of delegate type.
public delegate T GetAllNodesDelegate(int i);
private GetAllNodesDelegate getAllNodesDlg;
// Initilaize delegate field somehow, e.g. in constructor.
public SomeActionAccessor(GetAllNodesDelegate getAllNodesDlg)
{
this.getAllNodesDlg = getAllNodesDlg;
}
// Implement the method that calls the delegate.
public T GetAllNodes(int i)
{
return this.getAllNodesDlg(i);
}
}
The delegates can wrap both static and instance method. The only difference is that for creation delegate with instance method you need instance of the class who owns the method.
Let both ClassCurrent and MyClassLegacy implement an interface INodeFetcher:
public interface INodeFetcher<T> {
List<T> GetNodes(int k);
}
For ClassCurrent call the GetAllRootNodes method from the interface's implementation and for MyLegacyClass the GetAllLeaveNodes method.
Why would you want a delegate for this? It sounds overly complex. I would just create a method in a new class that you could instansiate when you needed to call you method. This class could be given some context information to help it decide. Then I would implement logic in the new method that would decide whether to call the current method or the legacy method.
Something like this:
public class CurrentOrLegacySelector<T>
{
public CurrentOrLegacySelector(some type that describe context)
{
// .. do something with the context.
// The context could be a boolean or something more fancy.
}
public List<T> GetNodes(int argument)
{
// Return the result of either current or
// legacy method based on context information
}
}
This would give you a clean wrapper for the methods that is easy to read and understand.
As a variation of the theme suggested by Rune Grimstad I think you could use the strategy pattern (e.g.
Introduction to the GOF Strategy Pattern in C# ).
This would be especially interesting in the case where you cannot change the LegacyClass (and therefore maybe cannot easily use the "interface approach" suggested by Cornelius) and if you are using dependency injection (DI; Dependency injection). DI would (maybe) let you inject the correct implementation (concrete strategy) in the right place.
Strategy:
public interface INodeFetcher<T> {
List<T> GetNodes(int k);
}
Concrete Strategies:
public class CurrentSelector<T> : INodeFetcher<T>
{
public List<T> GetNodes(int argument)
{
// Return the result "current" method
}
}
public class LegacySelector<T> : INodeFetcher<T>
{
public List<T> GetNodes(int argument)
{
// Return the result "legacy" method
}
}
-> Inject/instantiate the correct concrete strategy.
Regards
Currently I have the function CreateLog() for creating a a log4net Log with name after the constructing instance's class.
Typically used as in:
class MessageReceiver
{
protected ILog Log = Util.CreateLog();
...
}
If we remove lots of error handling the implementation boils down to:
[EDIT: Please read the longer version of CreateLog further on in this post.]
public ILog CreateLog()
{
System.Diagnostics.StackFrame stackFrame = new System.Diagnostics.StackFrame(1);
System.Reflection.MethodBase method = stackFrame.GetMethod();
return CreateLogWithName(method.DeclaringType.FullName);
}
Problem is that if we inheirit MessageReceiver into sub classes the log will still take its name from MessageReceiver since this is the declaring class of the method (constructor) which calls CreateLog.
class IMReceiver : MessageReceiver
{ ... }
class EmailReceiver : MessageReceiver
{ ... }
Instances of both these classes would get Logs with name "MessageReceiver" while I would like them to be given names "IMReceiver" and "EmailReceiver".
I know this can easily be done (and is done) by passing a reference to the object in creation when calling CreateLog since the GetType() method on object does what I want.
There are some minor reasons to prefer not adding the parameter and personally I feel disturbed by not finding a solution with no extra argument.
Is there anyone who can show me how to implement a zero argument CreateLog() that gets the name from the subclass and not the declaring class?
EDIT:
The CreateLog function does more than mentioned above. The reason for having one log per instance is to be able to differ between different instances in the logfile. This is enforced by the CreateLog/CreateLogWithName pair.
Expanding on the functionality of CreateLog() to motivate its existence.
public ILog CreateLog()
{
System.Diagnostics.StackFrame stackFrame = new System.Diagnostics.StackFrame(1);
System.Reflection.MethodBase method = stackFrame.GetMethod();
Type type = method.DeclaringType;
if (method.IsStatic)
{
return CreateLogWithName(type.FullName);
}
else
{
return CreateLogWithName(type.FullName + "-" + GetAndInstanceCountFor(type));
}
}
Also I prefer writing ILog Log = Util.CreateLog(); rather than copying in some long cryptic line from an other file whenever I write a new class. I am aware that the reflection used in Util.CreateLog is not guaranteed to work though - is System.Reflection.MethodBase.GetCurrentMethod() guaranteed to work?
Normally, MethodBase.ReflectedType would have your info. But, according to MSDN StackFrame.GetMethod:
The method that is currently executing may be inherited from a base class, although it is called in a derived class. In this case, the ReflectedType property of the MethodBase object that is returned by GetMethod identifies the base class, not the derived class.
which means you're probably out of luck.
I think you may be asking the wrong question. First of all the logger should be static to each class - each class should declare its own logger (to ensure that class names are properly reported AND to allow selective reporting of log messages filtered by project or namespace, from the config file.
Secondly it appears that you have created this method solely to identify the name of the calling class? If so we use this boilerplate code that is pasted into each class:
private static ILog log =
log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
Because it is private you ensure that your inheriting classes must declare their own logger and not use yours. Because it is static you ensure that the overhead of looking up the logger is only incurred once.
My apologies if you had different reasons for coding the Util.CreateLog() method.
Is there anyone who can show me how to implement a zero argument CreateLog() that gets the name from the subclass and not the declaring class?
I don't think you'll be able to do it by looking at the stack frame.
While your class is IMReceiver, the call to CreateLog method is in the MessageReceiver class. The stack frame must tell you where the method is being called from, or it wouldn't be any use, so it's always going to say MessageReceiver
If you called CreateLog explicitly in your IMReceiver and other classes, then it works, as the stack frame shows the method being called in the derived class (because it actually is).
Here's the best thing I can come up with:
class BaseClass{
public Log log = Utils.CreateLog();
}
class DerivedClass : BaseClass {
public DerivedClass() {
log = Utils.CreateLog();
}
}
If we trace creation of logs, we get this:
new BaseClass();
# Log created for BaseClass
new DerivedClass();
# Log created for BaseClass
# Log created for DerivedClass
The second 'log created for derived class' overwrites the instance variable, so your code will behave correctly, you'll just be creating a BaseClass log which immediately gets thrown away. This seems hacky and bad to me, I'd just go with specifying the type parameter in the constructor or using a generic.
IMHO specifying the type is cleaner than poking around in the stack frame anyway
If you can get it without looking at the stack frame, your options expand considerably
Try the StackTrace.GetFrames method. It returns an array of all the StackFrame objects in the call stack. Your caller should be at index one.
class Program
{
static void Main(string[] args)
{
Logger logger = new Logger();
Caller caller = new Caller();
caller.FirstMethod(logger);
caller.SecondMethod(logger);
}
}
public class Caller
{
public void FirstMethod(Logger logger)
{
Console.Out.WriteLine("first");
logger.Log();
}
public void SecondMethod(Logger logger)
{
Console.Out.WriteLine("second");
logger.Log();
}
}
public class Logger
{
public void Log()
{
StackTrace trace = new StackTrace();
var frames = trace.GetFrames();
Console.Out.WriteLine(frames[1].GetMethod().Name);
}
}
this outputs
first
FirstMethod
second
SecondMethod
Walk up the stack checking for base class - derived class relationship.
var type = new StackFrame(1).GetMethod().DeclaringType;
foreach (var frame in new StackTrace(2).GetFrames())
if (type != frame.GetMethod().DeclaringType.BaseType)
break;
else
type = frame.GetMethod().DeclaringType;
return CreateLogWithName(type.FullName);
You may want to put in a check that the methods examined are constructors. But a scenario where the subclass is instantiating the superclass in a method other than it's constructor, may still want the current behaviour.