Здравствуйте.
Начал изучать АОП, создаю UI save thread аспект:
public class FormsThreadAttribute : OnMethodInvocationAspect{
public override void OnInvocation(MethodInvocationEventArgs eventArgs)
{
Form f = (Form)eventArgs.Delegate.Target;
if (f.InvokeRequired)
f.Invoke(eventArgs.Delegate, eventArgs.GetArgumentArray());
else eventArgs.Proceed();
}
}
Но свойство Delegate у eventArgs отмечено как Obsolete, есть другой способ?
Спасибо.
Здравствуйте, alexsoff, Вы писали:
A>Начал изучать АОП, создаю UI save thread аспект:
A>public class FormsThreadAttribute : OnMethodInvocationAspect{
…
A>Но свойство Delegate у eventArgs отмечено как Obsolete, есть другой способ?
Внимательнее читайте сообщения компилятора
и прочую доступную вам информацию:
[ObsoleteAttribute("Use the Method and Instance properties instead.")]
public Delegate Delegate { get; }
здесь
Здравствуйте, _FRED_, Вы писали:
_FR>[/c#]
_FR>здесь
Это я читал, только вот что передавать
form.Invoke(Delegate.CreateDelegate(typeof(?????), eventArgs.Method), eventArgs.GetArgumentArray());
Где взять тип для создаваемого делегата?
Здравствуйте, alexsoff, Вы писали:
[/c#]
_FR>>здесь
A>Это я читал,
Тогда сразу надо было сказать об этом и точно спросить то, что интересует.
A>только вот что передавать
A>form.Invoke(Delegate.CreateDelegate(typeof(?????), eventArgs.Method), eventArgs.GetArgumentArray());
A>Где взять тип для создаваемого делегата?
Если я правильно понимаю, аспект срабатывает при вызове метода. Например, метод такой вот:
public void Test() { }
Какой должен быть делегат:
public delegate void Action();
или
public delegate void CrossAppDomainDelegate();
а может
public delegate void ThreadStart();
Видимо, и заобсолители свойство Delegate из-за его неоднозначности.
Для большинства случаев подойдёт что-то такое (поиск подходящего делегата из Action-ов и Func-ов, до четырёх параметров, без out\ref-параметров):
using System;
using System.Diagnostics;
using System.Reflection;
public static class DelegateHelper
{
#region Fields
private static readonly Type[] Actions = new[]
{
typeof(Action),
typeof(Action<>),
typeof(Action<,>),
typeof(Action<,,>),
typeof(Action<,,,>),
};
private static readonly Type[] Funcs = new[]
{
typeof(Func<>),
typeof(Func<,>),
typeof(Func<,,>),
typeof(Func<,,,>),
typeof(Func<,,,,>),
};
#endregion Fields
#region Constructor(s)
static DelegateHelper() {
Debug.Assert(Actions.Length == Funcs.Length, "Actions.Length == Funcs.Length");
}
#endregion Constructor(s)
#region Methods
public static Type GetDelegateType(MethodInfo info) {
if(info == null) {
throw new ArgumentNullException("info");
}//if
var action = info.ReturnType == typeof(void);
var types = action ? Actions : Funcs;
Debug.Assert(types != null, "types != null");
var parameters = Array.ConvertAll(info.GetParameters(), parameter => parameter.ParameterType);
if(parameters.Length > types.Length) {
throw new NotSupportedException();
}//if
var type = types[parameters.Length];
if(!action) {
var copy = new Type[parameters.Length + 1];
parameters.CopyTo(copy, 0);
parameters = copy;
parameters[parameters.Length - 1] = info.ReturnType;
}//if
return type.IsGenericTypeDefinition ? type.MakeGenericType(parameters) : type;
}
#endregion Methods
}
static class Program
{
static void Main() {
Converter<string, Type> converter = name => DelegateHelper.GetDelegateType(typeof(Program).GetMethod(name));
var t1 = converter("A0");
var t2 = converter("A1");
var t3 = converter("A2");
var t4 = converter("A3");
var t5 = converter("A4");
var t6 = converter("F0");
var t7 = converter("F1");
var t8 = converter("F2");
var t9 = converter("F3");
var tA = converter("F4");
}
public static void A0() { }
public static void A1(int x) { }
public static void A2(int x, int y) { }
public static void A3(int x, int y, int z) { }
public static void A4(int x, int y, int z, int w) { }
public static int F0() { return 0; }
public static int F1(int x) { return 0; }
public static int F2(int x, int y) { return 0; }
public static int F3(int x, int y, int z) { return 0; }
public static int F4(int x, int y, int z, int w) { return 0; }
}
Здравствуйте, alexsoff, Вы писали:
A>Где взять тип для создаваемого делегата?
Посмотрите пример со стартовой страницы сайта postsharp-а. Там как раз то, что вы пытаетесь написать.
Здравствуйте, Lloyd, Вы писали:
L>Посмотрите пример со стартовой страницы сайта postsharp-а. Там как раз то, что вы пытаетесь написать.
public class GuiThreadAttribute : OnMethodInvocationAspect
{
public override void OnInvocation(MethodInvocationEventArgs eventArgs)
{
DispatcherObject dispatcherObject = (DispatcherObject)eventArgs.Delegate.Target;
if (dispatcherObject.CheckAccess())
eventArgs.Proceed();
else
dispatcherObject.Dispatcher.Invoke( DispatcherPriority.Normal,
new Action(() => eventArgs.Proceed()));
}
}
Там они сами используют obsolete свойство.
Здравствуйте, alexsoff, Вы писали:
A>Но свойство Delegate у eventArgs отмечено как Obsolete, есть другой способ?
Решение оказалось до банальности простым:
[Serializable]
public class UIThreadInvokerAttribute : OnMethodInvocationAspect
{
#region Overrides of OnMethodInvocationAspect
/// <summary>
/// Method called instead of the intercepted method.
/// </summary>
/// <param name="eventArgs">Event arguments specifying which method
/// is being executed and which are its arguments. The implementation
/// should set the return value and ouput arguments.</param>
public override void OnInvocation( MethodInvocationEventArgs eventArgs )
{
Form form = eventArgs.Instance as Form;
if ( form!= null ) {
if ( form.InvokeRequired ) {
form.Invoke( new ThreadStart( () => eventArgs.Proceed() ) );
} else {
eventArgs.Proceed();
}
}
}
#endregion
}