PostSharp: Method *** should be annotated with a selector custom attribute because it is a master handler - postsharp

This code throw error: Method ...OnEntry(...) should be annotated with a selector custom attribute because it is a master handler.
[PSerializable]
public class LogRequestAttribute : MethodLevelAspect, IAspectProvider {
public IEnumerable<AspectInstance> ProvideAspects(object target) {
yield return new AspectInstance( target, new LogPlainRequest() );
}
}
[PSerializable]
public class LogPlainRequest : IMethodLevelAspect {
public void RuntimeInitialize(MethodBase method) {
}
[OnMethodEntryAdvice]
public void OnEntry(MethodExecutionArgs args) {
}
}
What is it error meaning? And what is wrong?

You can combine several related advices into one group (e.g. OnEntry, OnExit). This is what OnMethodBoundaryAspect does for you automatically. After you've grouped the advices you need to designate one of them as a "master advice". The properties and the pointcut of the group must be set on the master advice.
The pointcut assigned to the master advice acts as a selector of the advice's target element. The SelfPointcut, for example, simply selects the target of the aspect as the target of the advice. You can find more info and different pointcut kinds in the docs:
https://doc.postsharp.net/advices
In the example above you can apply the [SelfPointcut] attribute to the OnEntry method to get rid of the error message.
[PSerializable]
public class LogPlainRequest : IMethodLevelAspect {
public void RuntimeInitialize(MethodBase method) {
}
[OnMethodEntryAdvice]
[SelfPointcut]
public void OnEntry(MethodExecutionArgs args) {
}
}

Related

Spring AOP invoking some methods around Abstract method of Abstract class

I have an abstract class like
public abstract class EventHandler<T> {
public <T> void preProcess(Message<T> message) {
// do some pre-processing with the Message
}
protected abstract void handleEvent(Message<T> message) throws Exception;
public <T> void postProcess(Message<T> message) {
// do some post-processing with the Message
}
}
There are concrete classes which are extending from this Class.
I want to be able to invoke the preProcess() and postProcess() methods in the Abstract class using an #Around aspect when the handleEvent method is invoked on the concrete class.
I am trying to define the aspect like below
#Aspect
#Configuration
public class SomeAspect {
#Around(value = "execution(* com.handler.EventHandler+.handleEvent(..)))")
public void around(ProceedingJoinPoint proceedingJoinPoint) {
1. invoke preProcess
2. invoke the join point
3. invoke postProcess
}
}
How do i achieve what i am looking for?
Update
#Aspect
#Component
public class SomeAspect {
private Logger logger = LoggerFactory.getLogger(TenantAspect.class);
#Around(value = "execution(* com.handler.EventHandler+.handleEvent(..))) && within(com.handler..*) && this(eventHandler) && args(message))")
public void around(ProceedingJoinPoint proceedingJoinPoint, EventHandler<Object> eventHandler, Message<Object> message) {
}
}
Tried the above and compiler gives Unbound Pointcut Parameter for eventHandler and message
Following Aspect can do the same.
Explanation
execution(* com.handler.EventHandler+.handleEvent(..)) - execution of a method named handleEvent which is in a subtype of EventHandler
Designators
within(com.handler..*) - A scoping desginator to advice classes within the given package
Passing parameters to advice
this(eventHandler) - the object executing the method. target() may also be used
args(message) - argument passed at runtime
Notes
An aspect be better annotated with #Component and #Configuration be used for configurations.
within added to narrow the scope to advice.Please modify as needed
#Aspect
#Component
public class EventHandlerAspect {
#Around(value = "execution(* com.handler.EventHandler+.handleEvent(..)) "
+ "&& within(com.handler..*) "
+ "&& this(eventHandler) "
+ "&& args(message))")
public Object around(ProceedingJoinPoint proceedingJoinPoint,
EventHandler<Object> eventHandler,
Message<Object> message) throws Throwable {
Object obj = null;
// 1. invoke preProcess
eventHandler.preProcess(message);
try {
// 2. invoke the join point
obj = proceedingJoinPoint.proceed();
} finally {
// 3. invoke postProcess
eventHandler.postProcess(message);
}
return obj;
}
}
Hope this helps.
You can get the target object directly from the proceedingJoinPoint as follows:
((TestClass<Integer>) proceedingJoinPoint.getTarget()).preProcess(message);
//or
((TestClass<Object>) proceedingJoinPoint.getTarget()).preProcess(message);
You would need to know the generic's instantiation type and have a matching message object of the same type.
If the message is in the arguments of the intercepted function call you can get them as follows:
Object[] methodArguments = proceedingJoinPoint.getArgs();
Message<Integer> message = (Message<Integer>) methodArguments[0];
If message is the first argument, it will be in methodArguments[0]

mvvmcross touch command binding in android

I'm looking for a way to do a "Touch" command binding between axml and ViewModel, or some else like FocusChanged etc.
A simple "Click" command works fine like so:
local:MvxBind="{'Touch':{'Path':'CameraButtonCommand'}}" />
public IMvxCommand CameraButtonCommand
{
get
{
return new MvxRelayCommand(
() =>
{
RequestNavigate<AugRealityViewModel>(true);
})
;
}
}
However, I've tried other event types for the controll(in this case it's ImageButton) and they are not being processed. When I've checked the events listings in the View Class I see those:
public event EventHandler Click;
public event EventHandler<View.CreateContextMenuEventArgs> ContextMenuCreated;
public event EventHandler<View.FocusChangeEventArgs> FocusChange;
public event EventHandler<View.KeyEventArgs> KeyPress;
public event EventHandler<View.LongClickEventArgs> LongClick;
Only Click event has the general EventHandler attached to it, while other have genericed EventHandlers, and I'm wondering if that's the reason why it doesn't work.
I've also tried to attach a method to those events in the View class getting the proper control by FindViewById method and it works as expected this time around. But somehow I can't do it in the axml through Commands.
Also one more thing. The "Click" event is sending the "EventArgs" object as one of the parameters, and also the object reference. I can see that with ease if I do this behaviour in View Class, but when I do this by binding, I don't see those arguments when I'm processing the Command in ViewModel.
The framework can automatically bind any events which require EventHandler types. However, for any events which require a templated EventHandler (with custom EventArgs) then you are correct - you'll need to include a custom Binding.
The good news is that custom bindings are easy to write and to include.
For example, to bind:
public event EventHandler<View.LongClickEventArgs> LongClick;
you can include something like:
public class LongPressEventBinding
: MvxBaseAndroidTargetBinding
{
private readonly View _view;
private IMvxCommand _command;
public LongPressEventBinding(View view)
{
_view = view;
_view.LongClick += ViewOnLongClick;
}
private void ViewOnLongClick(object sender, View.LongClickEventArgs eventArgs)
{
if (_command != null)
{
_command.Execute();
}
}
public override void SetValue(object value)
{
_command = (IMvxCommand)value;
}
protected override void Dispose(bool isDisposing)
{
if (isDisposing)
{
_view.Click -= ViewOnLongClick;
}
base.Dispose(isDisposing);
}
public override Type TargetType
{
get { return typeof(IMvxCommand); }
}
public override MvxBindingMode DefaultMode
{
get { return MvxBindingMode.OneWay; }
}
}
Which can be configured in setup using something like:
protected override void FillTargetFactories(IMvxTargetBindingFactoryRegistry registry)
{
base.FillTargetFactories(registry);
registry.RegisterFactory(new MvxCustomBindingFactory<View>("LongPress", view => new LongPressEventBinding(view)));
}
Note that you can't write a single class that binds to all the different event types - as the compiler requires you to include the correct Type for the EventArgs. However, you could fairly easily change public class LongClickEventBinding to something like public class CustomEventBinding<TViewType, TEventArgsType> if you wanted to.
With regards to what argument you should pass into the IMvxCommand Execute method, I guess this depends a bit on the method in question, and it also depends on whether you need the ViewModel to support multiple platforms, or whether it is just for Android.

MEF Error when add item to list in constructor method

i write silverlight program very simple.i use Mef and WCF.
this code is MainPageViewModel class that included Commands and properties.
public List<NoOfStudentsDropDownItem> ListNoOfStudent{get;set;}
public MainPageViewModel()
{
InitializList();
}
private void InitializList()
{
ListNoOfStudent.Add(New NoOfStudentsDropDownItem(){DisplayText="1",NoOfStudent=-1});
ListNoOfStudent.Add(New NoOfStudentsDropDownItem(){DisplayText="5",NoOfStudent=5});
}
this is NoOfStudentsDropDownItem class;
public Class NoOfStudentsDropDownItem
{
public string DisplayText{get;set;}
public int NoofStudent{get;set}
}
this is part of App Class.
private void Application_Startup(object sender,StartupEventArgs e)
{
CompositionInitializer.SatisfyImports(this);
MainPage mainpage=new MainPage();
mainpage.DataContext=MainViewModel;
this.RootVisual=mainpage;
}
[Import]
public MainPageViewModel MainViewModel{get;set;}
i haven't error when commented InitializList method.i dont know cause.
You simply forgot to create the list. You declared a property for it, but it is never assigned so it will still be null when you call Add.

AOP using Windsor and bulk registering classes

I am trying to configure an application such that types from assemblyA can be used by my console to allow for logging in an AOP style. The JournalInterceptor will just write out method calls, input and maybe output arguments to a log file or datastore of some kind.
I can register one type at a time but I would like to register all types in one go. Once I get going I may add some filtering to the registered types but I am missing something.
I am trying to use Classes.FromAssemblyContaining but am not sure how to get at an IRegistration instance for the call to WindsorContainer::Register
Any clues?
// otherAssembly.cs
namespace assemblyA
{
public class Foo1 { public virtual void What(){} }
public class Foo2 { public virtual void Where(){} }
}
// program.cs
namespace console
{
using assemblyA;
public class JournalInterceptor : IInterceptor {}
public class Program
{
public static void Main()
{
var container = new Castle.Windsor.WindsorContainer()
.Register(
Component.For<JournalInterceptor>().LifeStyle.Transient,
// works but can't be the best way
Component.For<Foo1>().LifeStyle.Transient
.Interceptors<JournalInterceptor>(),
Component.For<Foo2>().LifeStyle.Transient,
.Interceptors<JournalInterceptor>(),
// how do I do it this way
Classes.FromAssemblyContaining<Foo1>()
.Pick()
.LifestyleTransient()
.Interceptors<JournalInterceptor>()
);
Foo1 foo = container.Resolve<Foo1>();
}
}
}
Implement a Pointcut. In Castle Windsor this is done by implementing the IModelInterceptorsSelector interface.
It would go something like this:
public class JournalPointcut : IModelInterceptorsSelector
{
public bool HasInterceptors(ComponentModel model)
{
return true; // intercept everything - probably not a good idea, though
}
public InterceptorReference[] SelectInterceptors(
ComponentModel model, InterceptorReference[] interceptors)
{
return new[]
{
InterceptorReference.ForType<JournalInterceptor>()
}.Concat(interceptors).ToArray();
}
}
Then register the Interceptor and the Pointcut with the container:
this.container.Register(Component.For<JounalInterceptor>());
this.container.Kernel.ProxyFactory.AddInterceptorSelector(new JournalPointcut());
For in-depth explanation, you may want to see this recording.

"No parameterless constructor" error instantiating Controller registered w/Windsor Container

Using MVC and trying to use dependency injection for controllers, but when I try to call a method on a controller that takes a dependency, I get the "no parameterless constructor" error. Here's my setup:
ProductRepository : IProductRepository
ProductService : IProductService {
public ProductService(IProductRepository repository) {} }
ProductController {
public ProductController(IProductService service) {} }
In Global.asax:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
InitializeServiceLocator();
RegisterRoutes(RouteTable.Routes);
}
protected virtual void InitializeServiceLocator()
{
IWindsorContainer container = new WindsorContainer();
ControllerBuilder.Current.SetControllerFactory(new WindsorControllerFactory(container));
container.RegisterControllers(typeof(HomeController).Assembly);
ComponentRegistrar.AddComponentsTo(container);
foreach (var handler in container.Kernel.GetAssignableHandlers(typeof(object)))
{
System.Diagnostics.Debug.WriteLine(String.Format("{0} {1}",
handler.ComponentModel.Service,
handler.ComponentModel.Implementation));
}
ServiceLocator.SetLocatorProvider(() => new WindsorServiceLocator(container));
}
ComponentRegistrar:
public static void AddComponentsTo(IWindsorContainer container)
{
AddCustomRepositoriesTo(container);
AddApplicationServicesTo(container);
}
When InitializeServiceLocator completes, I can see that all Controllers, Services and Repositories are registered.
Any help greatly appreciated.
I'd still like to know the problem, but I've worked around it by creating my own WindsorControllerFactory per this post (with modification to avoid any web.config action): http://mvcsharp.wordpress.com/2010/01/09/setting-up-ioc-in-asp-net-mvc-using-castle-windsor/
The WindsorControllerFactory in the previous code was the MvcContrib.Castle.WindsorControllerFactory. Anyone using MvcContrib version successfully?
Thanks.